sparclinux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 24/36] sparc32: Implement the new page table range API
       [not found] <20230315051444.3229621-1-willy@infradead.org>
@ 2023-03-15  5:14 ` Matthew Wilcox (Oracle)
  2023-03-15 10:11   ` Mike Rapoport
  2023-03-15  5:14 ` [PATCH v4 25/36] sparc64: " Matthew Wilcox (Oracle)
  1 sibling, 1 reply; 11+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-03-15  5:14 UTC (permalink / raw)
  To: linux-arch
  Cc: Matthew Wilcox (Oracle), linux-mm, linux-kernel, David S. Miller,
	sparclinux

Add PFN_PTE_SHIFT, update_mmu_cache_range(), flush_dcache_folio() and
flush_icache_pages().

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: sparclinux@vger.kernel.org
---
 arch/sparc/include/asm/cacheflush_32.h |  9 +++++++--
 arch/sparc/include/asm/pgtable_32.h    |  8 ++++----
 arch/sparc/mm/init_32.c                | 13 +++++++++++--
 3 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/arch/sparc/include/asm/cacheflush_32.h b/arch/sparc/include/asm/cacheflush_32.h
index adb6991d0455..8dba35d63328 100644
--- a/arch/sparc/include/asm/cacheflush_32.h
+++ b/arch/sparc/include/asm/cacheflush_32.h
@@ -16,6 +16,7 @@
 	sparc32_cachetlb_ops->cache_page(vma, addr)
 #define flush_icache_range(start, end)		do { } while (0)
 #define flush_icache_page(vma, pg)		do { } while (0)
+#define flush_icache_pages(vma, pg, nr)		do { } while (0)
 
 #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
 	do {							\
@@ -35,11 +36,15 @@
 #define flush_page_for_dma(addr) \
 	sparc32_cachetlb_ops->page_for_dma(addr)
 
-struct page;
 void sparc_flush_page_to_ram(struct page *page);
+void sparc_flush_folio_to_ram(struct folio *folio);
 
 #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
-#define flush_dcache_page(page)			sparc_flush_page_to_ram(page)
+#define flush_dcache_folio(folio)		sparc_flush_folio_to_ram(folio)
+static inline void flush_dcache_page(struct page *page)
+{
+	flush_dcache_folio(page_folio(page));
+}
 #define flush_dcache_mmap_lock(mapping)		do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)	do { } while (0)
 
diff --git a/arch/sparc/include/asm/pgtable_32.h b/arch/sparc/include/asm/pgtable_32.h
index d4330e3c57a6..7514611d14d3 100644
--- a/arch/sparc/include/asm/pgtable_32.h
+++ b/arch/sparc/include/asm/pgtable_32.h
@@ -101,8 +101,6 @@ static inline void set_pte(pte_t *ptep, pte_t pteval)
 	srmmu_swap((unsigned long *)ptep, pte_val(pteval));
 }
 
-#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
-
 static inline int srmmu_device_memory(unsigned long x)
 {
 	return ((x & 0xF0000000) != 0);
@@ -256,6 +254,7 @@ static inline pte_t pte_mkyoung(pte_t pte)
 	return __pte(pte_val(pte) | SRMMU_REF);
 }
 
+#define PFN_PTE_SHIFT			(PAGE_SHIFT - 4)
 #define pfn_pte(pfn, prot)		mk_pte(pfn_to_page(pfn), prot)
 
 static inline unsigned long pte_pfn(pte_t pte)
@@ -268,7 +267,7 @@ static inline unsigned long pte_pfn(pte_t pte)
 		 */
 		return ~0UL;
 	}
-	return (pte_val(pte) & SRMMU_PTE_PMASK) >> (PAGE_SHIFT-4);
+	return (pte_val(pte) & SRMMU_PTE_PMASK) >> PFN_PTE_SHIFT;
 }
 
 #define pte_page(pte)	pfn_to_page(pte_pfn(pte))
@@ -318,6 +317,7 @@ void mmu_info(struct seq_file *m);
 #define FAULT_CODE_USER     0x4
 
 #define update_mmu_cache(vma, address, ptep) do { } while (0)
+#define update_mmu_cache_range(vma, address, ptep, nr) do { } while (0)
 
 void srmmu_mapiorange(unsigned int bus, unsigned long xpa,
                       unsigned long xva, unsigned int len);
@@ -422,7 +422,7 @@ static inline int io_remap_pfn_range(struct vm_area_struct *vma,
 ({									  \
 	int __changed = !pte_same(*(__ptep), __entry);			  \
 	if (__changed) {						  \
-		set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry); \
+		set_pte(__ptep, __entry);				  \
 		flush_tlb_page(__vma, __address);			  \
 	}								  \
 	__changed;							  \
diff --git a/arch/sparc/mm/init_32.c b/arch/sparc/mm/init_32.c
index 9c0ea457bdf0..d96a14ffceeb 100644
--- a/arch/sparc/mm/init_32.c
+++ b/arch/sparc/mm/init_32.c
@@ -297,11 +297,20 @@ void sparc_flush_page_to_ram(struct page *page)
 {
 	unsigned long vaddr = (unsigned long)page_address(page);
 
-	if (vaddr)
-		__flush_page_to_ram(vaddr);
+	__flush_page_to_ram(vaddr);
 }
 EXPORT_SYMBOL(sparc_flush_page_to_ram);
 
+void sparc_flush_folio_to_ram(struct folio *folio)
+{
+	unsigned long vaddr = (unsigned long)folio_address(folio);
+	unsigned int i, nr = folio_nr_pages(folio);
+
+	for (i = 0; i < nr; i++)
+		__flush_page_to_ram(vaddr + i * PAGE_SIZE);
+}
+EXPORT_SYMBOL(sparc_flush_folio_to_ram);
+
 static const pgprot_t protection_map[16] = {
 	[VM_NONE]					= PAGE_NONE,
 	[VM_READ]					= PAGE_READONLY,
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v4 25/36] sparc64: Implement the new page table range API
       [not found] <20230315051444.3229621-1-willy@infradead.org>
  2023-03-15  5:14 ` [PATCH v4 24/36] sparc32: Implement the new page table range API Matthew Wilcox (Oracle)
@ 2023-03-15  5:14 ` Matthew Wilcox (Oracle)
  2023-03-15 10:11   ` Mike Rapoport
  2025-08-03 12:05   ` John Paul Adrian Glaubitz
  1 sibling, 2 replies; 11+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-03-15  5:14 UTC (permalink / raw)
  To: linux-arch
  Cc: Matthew Wilcox (Oracle), linux-mm, linux-kernel, David S. Miller,
	sparclinux

Add set_ptes(), update_mmu_cache_range(), flush_dcache_folio() and
flush_icache_pages().  Convert the PG_dcache_dirty flag from being
per-page to per-folio.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: sparclinux@vger.kernel.org
---
 arch/sparc/include/asm/cacheflush_64.h | 18 ++++--
 arch/sparc/include/asm/pgtable_64.h    | 24 ++++++--
 arch/sparc/kernel/smp_64.c             | 56 +++++++++++-------
 arch/sparc/mm/init_64.c                | 78 +++++++++++++++-----------
 arch/sparc/mm/tlb.c                    |  5 +-
 5 files changed, 116 insertions(+), 65 deletions(-)

diff --git a/arch/sparc/include/asm/cacheflush_64.h b/arch/sparc/include/asm/cacheflush_64.h
index b9341836597e..a9a719f04d06 100644
--- a/arch/sparc/include/asm/cacheflush_64.h
+++ b/arch/sparc/include/asm/cacheflush_64.h
@@ -35,20 +35,26 @@ void flush_icache_range(unsigned long start, unsigned long end);
 void __flush_icache_page(unsigned long);
 
 void __flush_dcache_page(void *addr, int flush_icache);
-void flush_dcache_page_impl(struct page *page);
+void flush_dcache_folio_impl(struct folio *folio);
 #ifdef CONFIG_SMP
-void smp_flush_dcache_page_impl(struct page *page, int cpu);
-void flush_dcache_page_all(struct mm_struct *mm, struct page *page);
+void smp_flush_dcache_folio_impl(struct folio *folio, int cpu);
+void flush_dcache_folio_all(struct mm_struct *mm, struct folio *folio);
 #else
-#define smp_flush_dcache_page_impl(page,cpu) flush_dcache_page_impl(page)
-#define flush_dcache_page_all(mm,page) flush_dcache_page_impl(page)
+#define smp_flush_dcache_folio_impl(folio, cpu) flush_dcache_folio_impl(folio)
+#define flush_dcache_folio_all(mm, folio) flush_dcache_folio_impl(folio)
 #endif
 
 void __flush_dcache_range(unsigned long start, unsigned long end);
 #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
-void flush_dcache_page(struct page *page);
+void flush_dcache_folio(struct folio *folio);
+#define flush_dcache_folio flush_dcache_folio
+static inline void flush_dcache_page(struct page *page)
+{
+	flush_dcache_folio(page_folio(page));
+}
 
 #define flush_icache_page(vma, pg)	do { } while(0)
+#define flush_icache_pages(vma, pg, nr)	do { } while(0)
 
 void flush_ptrace_access(struct vm_area_struct *, struct page *,
 			 unsigned long uaddr, void *kaddr,
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
index 2dc8d4641734..49c37000e1b1 100644
--- a/arch/sparc/include/asm/pgtable_64.h
+++ b/arch/sparc/include/asm/pgtable_64.h
@@ -911,8 +911,19 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
 	maybe_tlb_batch_add(mm, addr, ptep, orig, fullmm, PAGE_SHIFT);
 }
 
-#define set_pte_at(mm,addr,ptep,pte)	\
-	__set_pte_at((mm), (addr), (ptep), (pte), 0)
+static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
+		pte_t *ptep, pte_t pte, unsigned int nr)
+{
+	for (;;) {
+		__set_pte_at(mm, addr, ptep, pte, 0);
+		if (--nr == 0)
+			break;
+		ptep++;
+		pte_val(pte) += PAGE_SIZE;
+		addr += PAGE_SIZE;
+	}
+}
+#define set_ptes set_ptes
 
 #define pte_clear(mm,addr,ptep)		\
 	set_pte_at((mm), (addr), (ptep), __pte(0UL))
@@ -931,8 +942,8 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
 									\
 		if (pfn_valid(this_pfn) &&				\
 		    (((old_addr) ^ (new_addr)) & (1 << 13)))		\
-			flush_dcache_page_all(current->mm,		\
-					      pfn_to_page(this_pfn));	\
+			flush_dcache_folio_all(current->mm,		\
+				page_folio(pfn_to_page(this_pfn)));	\
 	}								\
 	newpte;								\
 })
@@ -947,7 +958,10 @@ struct seq_file;
 void mmu_info(struct seq_file *);
 
 struct vm_area_struct;
-void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t *);
+void update_mmu_cache_range(struct vm_area_struct *, unsigned long addr,
+		pte_t *ptep, unsigned int nr);
+#define update_mmu_cache(vma, addr, ptep) \
+	update_mmu_cache_range(vma, addr, ptep, 1)
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr,
 			  pmd_t *pmd);
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
index a55295d1b924..90ef8677ac89 100644
--- a/arch/sparc/kernel/smp_64.c
+++ b/arch/sparc/kernel/smp_64.c
@@ -921,20 +921,26 @@ extern unsigned long xcall_flush_dcache_page_cheetah;
 #endif
 extern unsigned long xcall_flush_dcache_page_spitfire;
 
-static inline void __local_flush_dcache_page(struct page *page)
+static inline void __local_flush_dcache_folio(struct folio *folio)
 {
+	unsigned int i, nr = folio_nr_pages(folio);
+
 #ifdef DCACHE_ALIASING_POSSIBLE
-	__flush_dcache_page(page_address(page),
+	for (i = 0; i < nr; i++)
+		__flush_dcache_page(folio_address(folio) + i * PAGE_SIZE,
 			    ((tlb_type == spitfire) &&
-			     page_mapping_file(page) != NULL));
+			     folio_flush_mapping(folio) != NULL));
 #else
-	if (page_mapping_file(page) != NULL &&
-	    tlb_type == spitfire)
-		__flush_icache_page(__pa(page_address(page)));
+	if (folio_flush_mapping(folio) != NULL &&
+	    tlb_type == spitfire) {
+		unsigned long pfn = folio_pfn(folio)
+		for (i = 0; i < nr; i++)
+			__flush_icache_page((pfn + i) * PAGE_SIZE);
+	}
 #endif
 }
 
-void smp_flush_dcache_page_impl(struct page *page, int cpu)
+void smp_flush_dcache_folio_impl(struct folio *folio, int cpu)
 {
 	int this_cpu;
 
@@ -948,14 +954,14 @@ void smp_flush_dcache_page_impl(struct page *page, int cpu)
 	this_cpu = get_cpu();
 
 	if (cpu == this_cpu) {
-		__local_flush_dcache_page(page);
+		__local_flush_dcache_folio(folio);
 	} else if (cpu_online(cpu)) {
-		void *pg_addr = page_address(page);
+		void *pg_addr = folio_address(folio);
 		u64 data0 = 0;
 
 		if (tlb_type == spitfire) {
 			data0 = ((u64)&xcall_flush_dcache_page_spitfire);
-			if (page_mapping_file(page) != NULL)
+			if (folio_flush_mapping(folio) != NULL)
 				data0 |= ((u64)1 << 32);
 		} else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
 #ifdef DCACHE_ALIASING_POSSIBLE
@@ -963,18 +969,23 @@ void smp_flush_dcache_page_impl(struct page *page, int cpu)
 #endif
 		}
 		if (data0) {
-			xcall_deliver(data0, __pa(pg_addr),
-				      (u64) pg_addr, cpumask_of(cpu));
+			unsigned int i, nr = folio_nr_pages(folio);
+
+			for (i = 0; i < nr; i++) {
+				xcall_deliver(data0, __pa(pg_addr),
+					      (u64) pg_addr, cpumask_of(cpu));
 #ifdef CONFIG_DEBUG_DCFLUSH
-			atomic_inc(&dcpage_flushes_xcall);
+				atomic_inc(&dcpage_flushes_xcall);
 #endif
+				pg_addr += PAGE_SIZE;
+			}
 		}
 	}
 
 	put_cpu();
 }
 
-void flush_dcache_page_all(struct mm_struct *mm, struct page *page)
+void flush_dcache_folio_all(struct mm_struct *mm, struct folio *folio)
 {
 	void *pg_addr;
 	u64 data0;
@@ -988,10 +999,10 @@ void flush_dcache_page_all(struct mm_struct *mm, struct page *page)
 	atomic_inc(&dcpage_flushes);
 #endif
 	data0 = 0;
-	pg_addr = page_address(page);
+	pg_addr = folio_address(folio);
 	if (tlb_type == spitfire) {
 		data0 = ((u64)&xcall_flush_dcache_page_spitfire);
-		if (page_mapping_file(page) != NULL)
+		if (folio_flush_mapping(folio) != NULL)
 			data0 |= ((u64)1 << 32);
 	} else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
 #ifdef DCACHE_ALIASING_POSSIBLE
@@ -999,13 +1010,18 @@ void flush_dcache_page_all(struct mm_struct *mm, struct page *page)
 #endif
 	}
 	if (data0) {
-		xcall_deliver(data0, __pa(pg_addr),
-			      (u64) pg_addr, cpu_online_mask);
+		unsigned int i, nr = folio_nr_pages(folio);
+
+		for (i = 0; i < nr; i++) {
+			xcall_deliver(data0, __pa(pg_addr),
+				      (u64) pg_addr, cpu_online_mask);
 #ifdef CONFIG_DEBUG_DCFLUSH
-		atomic_inc(&dcpage_flushes_xcall);
+			atomic_inc(&dcpage_flushes_xcall);
 #endif
+			pg_addr += PAGE_SIZE;
+		}
 	}
-	__local_flush_dcache_page(page);
+	__local_flush_dcache_folio(folio);
 
 	preempt_enable();
 }
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 04f9db0c3111..ab9aacbaf43c 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -195,21 +195,26 @@ atomic_t dcpage_flushes_xcall = ATOMIC_INIT(0);
 #endif
 #endif
 
-inline void flush_dcache_page_impl(struct page *page)
+inline void flush_dcache_folio_impl(struct folio *folio)
 {
+	unsigned int i, nr = folio_nr_pages(folio);
+
 	BUG_ON(tlb_type == hypervisor);
 #ifdef CONFIG_DEBUG_DCFLUSH
 	atomic_inc(&dcpage_flushes);
 #endif
 
 #ifdef DCACHE_ALIASING_POSSIBLE
-	__flush_dcache_page(page_address(page),
-			    ((tlb_type == spitfire) &&
-			     page_mapping_file(page) != NULL));
+	for (i = 0; i < nr; i++)
+		__flush_dcache_page(folio_address(folio) + i * PAGE_SIZE,
+				    ((tlb_type == spitfire) &&
+				     folio_flush_mapping(folio) != NULL));
 #else
-	if (page_mapping_file(page) != NULL &&
-	    tlb_type == spitfire)
-		__flush_icache_page(__pa(page_address(page)));
+	if (folio_flush_mapping(folio) != NULL &&
+	    tlb_type == spitfire) {
+		for (i = 0; i < nr; i++)
+			__flush_icache_page((pfn + i) * PAGE_SIZE);
+	}
 #endif
 }
 
@@ -218,10 +223,10 @@ inline void flush_dcache_page_impl(struct page *page)
 #define PG_dcache_cpu_mask	\
 	((1UL<<ilog2(roundup_pow_of_two(NR_CPUS)))-1UL)
 
-#define dcache_dirty_cpu(page) \
-	(((page)->flags >> PG_dcache_cpu_shift) & PG_dcache_cpu_mask)
+#define dcache_dirty_cpu(folio) \
+	(((folio)->flags >> PG_dcache_cpu_shift) & PG_dcache_cpu_mask)
 
-static inline void set_dcache_dirty(struct page *page, int this_cpu)
+static inline void set_dcache_dirty(struct folio *folio, int this_cpu)
 {
 	unsigned long mask = this_cpu;
 	unsigned long non_cpu_bits;
@@ -238,11 +243,11 @@ static inline void set_dcache_dirty(struct page *page, int this_cpu)
 			     "bne,pn	%%xcc, 1b\n\t"
 			     " nop"
 			     : /* no outputs */
-			     : "r" (mask), "r" (non_cpu_bits), "r" (&page->flags)
+			     : "r" (mask), "r" (non_cpu_bits), "r" (&folio->flags)
 			     : "g1", "g7");
 }
 
-static inline void clear_dcache_dirty_cpu(struct page *page, unsigned long cpu)
+static inline void clear_dcache_dirty_cpu(struct folio *folio, unsigned long cpu)
 {
 	unsigned long mask = (1UL << PG_dcache_dirty);
 
@@ -260,7 +265,7 @@ static inline void clear_dcache_dirty_cpu(struct page *page, unsigned long cpu)
 			     " nop\n"
 			     "2:"
 			     : /* no outputs */
-			     : "r" (cpu), "r" (mask), "r" (&page->flags),
+			     : "r" (cpu), "r" (mask), "r" (&folio->flags),
 			       "i" (PG_dcache_cpu_mask),
 			       "i" (PG_dcache_cpu_shift)
 			     : "g1", "g7");
@@ -284,9 +289,10 @@ static void flush_dcache(unsigned long pfn)
 
 	page = pfn_to_page(pfn);
 	if (page) {
+		struct folio *folio = page_folio(page);
 		unsigned long pg_flags;
 
-		pg_flags = page->flags;
+		pg_flags = folio->flags;
 		if (pg_flags & (1UL << PG_dcache_dirty)) {
 			int cpu = ((pg_flags >> PG_dcache_cpu_shift) &
 				   PG_dcache_cpu_mask);
@@ -296,11 +302,11 @@ static void flush_dcache(unsigned long pfn)
 			 * in the SMP case.
 			 */
 			if (cpu == this_cpu)
-				flush_dcache_page_impl(page);
+				flush_dcache_folio_impl(folio);
 			else
-				smp_flush_dcache_page_impl(page, cpu);
+				smp_flush_dcache_folio_impl(folio, cpu);
 
-			clear_dcache_dirty_cpu(page, cpu);
+			clear_dcache_dirty_cpu(folio, cpu);
 
 			put_cpu();
 		}
@@ -388,12 +394,14 @@ bool __init arch_hugetlb_valid_size(unsigned long size)
 }
 #endif	/* CONFIG_HUGETLB_PAGE */
 
-void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
+void update_mmu_cache_range(struct vm_area_struct *vma, unsigned long address,
+		pte_t *ptep, unsigned int nr)
 {
 	struct mm_struct *mm;
 	unsigned long flags;
 	bool is_huge_tsb;
 	pte_t pte = *ptep;
+	unsigned int i;
 
 	if (tlb_type != hypervisor) {
 		unsigned long pfn = pte_pfn(pte);
@@ -440,15 +448,21 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *
 		}
 	}
 #endif
-	if (!is_huge_tsb)
-		__update_mmu_tsb_insert(mm, MM_TSB_BASE, PAGE_SHIFT,
-					address, pte_val(pte));
+	if (!is_huge_tsb) {
+		for (i = 0; i < nr; i++) {
+			__update_mmu_tsb_insert(mm, MM_TSB_BASE, PAGE_SHIFT,
+						address, pte_val(pte));
+			address += PAGE_SIZE;
+			pte_val(pte) += PAGE_SIZE;
+		}
+	}
 
 	spin_unlock_irqrestore(&mm->context.lock, flags);
 }
 
-void flush_dcache_page(struct page *page)
+void flush_dcache_folio(struct folio *folio)
 {
+	unsigned long pfn = folio_pfn(folio);
 	struct address_space *mapping;
 	int this_cpu;
 
@@ -459,35 +473,35 @@ void flush_dcache_page(struct page *page)
 	 * is merely the zero page.  The 'bigcore' testcase in GDB
 	 * causes this case to run millions of times.
 	 */
-	if (page == ZERO_PAGE(0))
+	if (is_zero_pfn(pfn))
 		return;
 
 	this_cpu = get_cpu();
 
-	mapping = page_mapping_file(page);
+	mapping = folio_flush_mapping(folio);
 	if (mapping && !mapping_mapped(mapping)) {
-		int dirty = test_bit(PG_dcache_dirty, &page->flags);
+		bool dirty = test_bit(PG_dcache_dirty, &folio->flags);
 		if (dirty) {
-			int dirty_cpu = dcache_dirty_cpu(page);
+			int dirty_cpu = dcache_dirty_cpu(folio);
 
 			if (dirty_cpu == this_cpu)
 				goto out;
-			smp_flush_dcache_page_impl(page, dirty_cpu);
+			smp_flush_dcache_folio_impl(folio, dirty_cpu);
 		}
-		set_dcache_dirty(page, this_cpu);
+		set_dcache_dirty(folio, this_cpu);
 	} else {
 		/* We could delay the flush for the !page_mapping
 		 * case too.  But that case is for exec env/arg
 		 * pages and those are %99 certainly going to get
 		 * faulted into the tlb (and thus flushed) anyways.
 		 */
-		flush_dcache_page_impl(page);
+		flush_dcache_folio_impl(folio);
 	}
 
 out:
 	put_cpu();
 }
-EXPORT_SYMBOL(flush_dcache_page);
+EXPORT_SYMBOL(flush_dcache_folio);
 
 void __kprobes flush_icache_range(unsigned long start, unsigned long end)
 {
@@ -2280,10 +2294,10 @@ void __init paging_init(void)
 	setup_page_offset();
 
 	/* These build time checkes make sure that the dcache_dirty_cpu()
-	 * page->flags usage will work.
+	 * folio->flags usage will work.
 	 *
 	 * When a page gets marked as dcache-dirty, we store the
-	 * cpu number starting at bit 32 in the page->flags.  Also,
+	 * cpu number starting at bit 32 in the folio->flags.  Also,
 	 * functions like clear_dcache_dirty_cpu use the cpu mask
 	 * in 13-bit signed-immediate instruction fields.
 	 */
diff --git a/arch/sparc/mm/tlb.c b/arch/sparc/mm/tlb.c
index 9a725547578e..3fa6a070912d 100644
--- a/arch/sparc/mm/tlb.c
+++ b/arch/sparc/mm/tlb.c
@@ -118,6 +118,7 @@ void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr,
 		unsigned long paddr, pfn = pte_pfn(orig);
 		struct address_space *mapping;
 		struct page *page;
+		struct folio *folio;
 
 		if (!pfn_valid(pfn))
 			goto no_cache_flush;
@@ -127,13 +128,13 @@ void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr,
 			goto no_cache_flush;
 
 		/* A real file page? */
-		mapping = page_mapping_file(page);
+		mapping = folio_flush_mapping(folio);
 		if (!mapping)
 			goto no_cache_flush;
 
 		paddr = (unsigned long) page_address(page);
 		if ((paddr ^ vaddr) & (1 << 13))
-			flush_dcache_page_all(mm, page);
+			flush_dcache_folio_all(mm, folio);
 	}
 
 no_cache_flush:
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH v4 24/36] sparc32: Implement the new page table range API
  2023-03-15  5:14 ` [PATCH v4 24/36] sparc32: Implement the new page table range API Matthew Wilcox (Oracle)
@ 2023-03-15 10:11   ` Mike Rapoport
  0 siblings, 0 replies; 11+ messages in thread
From: Mike Rapoport @ 2023-03-15 10:11 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle)
  Cc: linux-arch, linux-mm, linux-kernel, David S. Miller, sparclinux

On Wed, Mar 15, 2023 at 05:14:32AM +0000, Matthew Wilcox (Oracle) wrote:
> Add PFN_PTE_SHIFT, update_mmu_cache_range(), flush_dcache_folio() and
> flush_icache_pages().
> 
> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: sparclinux@vger.kernel.org

Acked-by: Mike Rapoport (IBM) <rppt@kernel.org>

> ---
>  arch/sparc/include/asm/cacheflush_32.h |  9 +++++++--
>  arch/sparc/include/asm/pgtable_32.h    |  8 ++++----
>  arch/sparc/mm/init_32.c                | 13 +++++++++++--
>  3 files changed, 22 insertions(+), 8 deletions(-)
> 
> diff --git a/arch/sparc/include/asm/cacheflush_32.h b/arch/sparc/include/asm/cacheflush_32.h
> index adb6991d0455..8dba35d63328 100644
> --- a/arch/sparc/include/asm/cacheflush_32.h
> +++ b/arch/sparc/include/asm/cacheflush_32.h
> @@ -16,6 +16,7 @@
>  	sparc32_cachetlb_ops->cache_page(vma, addr)
>  #define flush_icache_range(start, end)		do { } while (0)
>  #define flush_icache_page(vma, pg)		do { } while (0)
> +#define flush_icache_pages(vma, pg, nr)		do { } while (0)
>  
>  #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
>  	do {							\
> @@ -35,11 +36,15 @@
>  #define flush_page_for_dma(addr) \
>  	sparc32_cachetlb_ops->page_for_dma(addr)
>  
> -struct page;
>  void sparc_flush_page_to_ram(struct page *page);
> +void sparc_flush_folio_to_ram(struct folio *folio);
>  
>  #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
> -#define flush_dcache_page(page)			sparc_flush_page_to_ram(page)
> +#define flush_dcache_folio(folio)		sparc_flush_folio_to_ram(folio)
> +static inline void flush_dcache_page(struct page *page)
> +{
> +	flush_dcache_folio(page_folio(page));
> +}
>  #define flush_dcache_mmap_lock(mapping)		do { } while (0)
>  #define flush_dcache_mmap_unlock(mapping)	do { } while (0)
>  
> diff --git a/arch/sparc/include/asm/pgtable_32.h b/arch/sparc/include/asm/pgtable_32.h
> index d4330e3c57a6..7514611d14d3 100644
> --- a/arch/sparc/include/asm/pgtable_32.h
> +++ b/arch/sparc/include/asm/pgtable_32.h
> @@ -101,8 +101,6 @@ static inline void set_pte(pte_t *ptep, pte_t pteval)
>  	srmmu_swap((unsigned long *)ptep, pte_val(pteval));
>  }
>  
> -#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
> -
>  static inline int srmmu_device_memory(unsigned long x)
>  {
>  	return ((x & 0xF0000000) != 0);
> @@ -256,6 +254,7 @@ static inline pte_t pte_mkyoung(pte_t pte)
>  	return __pte(pte_val(pte) | SRMMU_REF);
>  }
>  
> +#define PFN_PTE_SHIFT			(PAGE_SHIFT - 4)
>  #define pfn_pte(pfn, prot)		mk_pte(pfn_to_page(pfn), prot)
>  
>  static inline unsigned long pte_pfn(pte_t pte)
> @@ -268,7 +267,7 @@ static inline unsigned long pte_pfn(pte_t pte)
>  		 */
>  		return ~0UL;
>  	}
> -	return (pte_val(pte) & SRMMU_PTE_PMASK) >> (PAGE_SHIFT-4);
> +	return (pte_val(pte) & SRMMU_PTE_PMASK) >> PFN_PTE_SHIFT;
>  }
>  
>  #define pte_page(pte)	pfn_to_page(pte_pfn(pte))
> @@ -318,6 +317,7 @@ void mmu_info(struct seq_file *m);
>  #define FAULT_CODE_USER     0x4
>  
>  #define update_mmu_cache(vma, address, ptep) do { } while (0)
> +#define update_mmu_cache_range(vma, address, ptep, nr) do { } while (0)
>  
>  void srmmu_mapiorange(unsigned int bus, unsigned long xpa,
>                        unsigned long xva, unsigned int len);
> @@ -422,7 +422,7 @@ static inline int io_remap_pfn_range(struct vm_area_struct *vma,
>  ({									  \
>  	int __changed = !pte_same(*(__ptep), __entry);			  \
>  	if (__changed) {						  \
> -		set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry); \
> +		set_pte(__ptep, __entry);				  \
>  		flush_tlb_page(__vma, __address);			  \
>  	}								  \
>  	__changed;							  \
> diff --git a/arch/sparc/mm/init_32.c b/arch/sparc/mm/init_32.c
> index 9c0ea457bdf0..d96a14ffceeb 100644
> --- a/arch/sparc/mm/init_32.c
> +++ b/arch/sparc/mm/init_32.c
> @@ -297,11 +297,20 @@ void sparc_flush_page_to_ram(struct page *page)
>  {
>  	unsigned long vaddr = (unsigned long)page_address(page);
>  
> -	if (vaddr)
> -		__flush_page_to_ram(vaddr);
> +	__flush_page_to_ram(vaddr);
>  }
>  EXPORT_SYMBOL(sparc_flush_page_to_ram);
>  
> +void sparc_flush_folio_to_ram(struct folio *folio)
> +{
> +	unsigned long vaddr = (unsigned long)folio_address(folio);
> +	unsigned int i, nr = folio_nr_pages(folio);
> +
> +	for (i = 0; i < nr; i++)
> +		__flush_page_to_ram(vaddr + i * PAGE_SIZE);
> +}
> +EXPORT_SYMBOL(sparc_flush_folio_to_ram);
> +
>  static const pgprot_t protection_map[16] = {
>  	[VM_NONE]					= PAGE_NONE,
>  	[VM_READ]					= PAGE_READONLY,
> -- 
> 2.39.2
> 
> 

-- 
Sincerely yours,
Mike.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v4 25/36] sparc64: Implement the new page table range API
  2023-03-15  5:14 ` [PATCH v4 25/36] sparc64: " Matthew Wilcox (Oracle)
@ 2023-03-15 10:11   ` Mike Rapoport
  2025-08-03 12:05   ` John Paul Adrian Glaubitz
  1 sibling, 0 replies; 11+ messages in thread
From: Mike Rapoport @ 2023-03-15 10:11 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle)
  Cc: linux-arch, linux-mm, linux-kernel, David S. Miller, sparclinux

On Wed, Mar 15, 2023 at 05:14:33AM +0000, Matthew Wilcox (Oracle) wrote:
> Add set_ptes(), update_mmu_cache_range(), flush_dcache_folio() and
> flush_icache_pages().  Convert the PG_dcache_dirty flag from being
> per-page to per-folio.
> 
> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: sparclinux@vger.kernel.org

Acked-by: Mike Rapoport (IBM) <rppt@kernel.org>

> ---
>  arch/sparc/include/asm/cacheflush_64.h | 18 ++++--
>  arch/sparc/include/asm/pgtable_64.h    | 24 ++++++--
>  arch/sparc/kernel/smp_64.c             | 56 +++++++++++-------
>  arch/sparc/mm/init_64.c                | 78 +++++++++++++++-----------
>  arch/sparc/mm/tlb.c                    |  5 +-
>  5 files changed, 116 insertions(+), 65 deletions(-)
> 
> diff --git a/arch/sparc/include/asm/cacheflush_64.h b/arch/sparc/include/asm/cacheflush_64.h
> index b9341836597e..a9a719f04d06 100644
> --- a/arch/sparc/include/asm/cacheflush_64.h
> +++ b/arch/sparc/include/asm/cacheflush_64.h
> @@ -35,20 +35,26 @@ void flush_icache_range(unsigned long start, unsigned long end);
>  void __flush_icache_page(unsigned long);
>  
>  void __flush_dcache_page(void *addr, int flush_icache);
> -void flush_dcache_page_impl(struct page *page);
> +void flush_dcache_folio_impl(struct folio *folio);
>  #ifdef CONFIG_SMP
> -void smp_flush_dcache_page_impl(struct page *page, int cpu);
> -void flush_dcache_page_all(struct mm_struct *mm, struct page *page);
> +void smp_flush_dcache_folio_impl(struct folio *folio, int cpu);
> +void flush_dcache_folio_all(struct mm_struct *mm, struct folio *folio);
>  #else
> -#define smp_flush_dcache_page_impl(page,cpu) flush_dcache_page_impl(page)
> -#define flush_dcache_page_all(mm,page) flush_dcache_page_impl(page)
> +#define smp_flush_dcache_folio_impl(folio, cpu) flush_dcache_folio_impl(folio)
> +#define flush_dcache_folio_all(mm, folio) flush_dcache_folio_impl(folio)
>  #endif
>  
>  void __flush_dcache_range(unsigned long start, unsigned long end);
>  #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
> -void flush_dcache_page(struct page *page);
> +void flush_dcache_folio(struct folio *folio);
> +#define flush_dcache_folio flush_dcache_folio
> +static inline void flush_dcache_page(struct page *page)
> +{
> +	flush_dcache_folio(page_folio(page));
> +}
>  
>  #define flush_icache_page(vma, pg)	do { } while(0)
> +#define flush_icache_pages(vma, pg, nr)	do { } while(0)
>  
>  void flush_ptrace_access(struct vm_area_struct *, struct page *,
>  			 unsigned long uaddr, void *kaddr,
> diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
> index 2dc8d4641734..49c37000e1b1 100644
> --- a/arch/sparc/include/asm/pgtable_64.h
> +++ b/arch/sparc/include/asm/pgtable_64.h
> @@ -911,8 +911,19 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
>  	maybe_tlb_batch_add(mm, addr, ptep, orig, fullmm, PAGE_SHIFT);
>  }
>  
> -#define set_pte_at(mm,addr,ptep,pte)	\
> -	__set_pte_at((mm), (addr), (ptep), (pte), 0)
> +static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
> +		pte_t *ptep, pte_t pte, unsigned int nr)
> +{
> +	for (;;) {
> +		__set_pte_at(mm, addr, ptep, pte, 0);
> +		if (--nr == 0)
> +			break;
> +		ptep++;
> +		pte_val(pte) += PAGE_SIZE;
> +		addr += PAGE_SIZE;
> +	}
> +}
> +#define set_ptes set_ptes
>  
>  #define pte_clear(mm,addr,ptep)		\
>  	set_pte_at((mm), (addr), (ptep), __pte(0UL))
> @@ -931,8 +942,8 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
>  									\
>  		if (pfn_valid(this_pfn) &&				\
>  		    (((old_addr) ^ (new_addr)) & (1 << 13)))		\
> -			flush_dcache_page_all(current->mm,		\
> -					      pfn_to_page(this_pfn));	\
> +			flush_dcache_folio_all(current->mm,		\
> +				page_folio(pfn_to_page(this_pfn)));	\
>  	}								\
>  	newpte;								\
>  })
> @@ -947,7 +958,10 @@ struct seq_file;
>  void mmu_info(struct seq_file *);
>  
>  struct vm_area_struct;
> -void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t *);
> +void update_mmu_cache_range(struct vm_area_struct *, unsigned long addr,
> +		pte_t *ptep, unsigned int nr);
> +#define update_mmu_cache(vma, addr, ptep) \
> +	update_mmu_cache_range(vma, addr, ptep, 1)
>  #ifdef CONFIG_TRANSPARENT_HUGEPAGE
>  void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr,
>  			  pmd_t *pmd);
> diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
> index a55295d1b924..90ef8677ac89 100644
> --- a/arch/sparc/kernel/smp_64.c
> +++ b/arch/sparc/kernel/smp_64.c
> @@ -921,20 +921,26 @@ extern unsigned long xcall_flush_dcache_page_cheetah;
>  #endif
>  extern unsigned long xcall_flush_dcache_page_spitfire;
>  
> -static inline void __local_flush_dcache_page(struct page *page)
> +static inline void __local_flush_dcache_folio(struct folio *folio)
>  {
> +	unsigned int i, nr = folio_nr_pages(folio);
> +
>  #ifdef DCACHE_ALIASING_POSSIBLE
> -	__flush_dcache_page(page_address(page),
> +	for (i = 0; i < nr; i++)
> +		__flush_dcache_page(folio_address(folio) + i * PAGE_SIZE,
>  			    ((tlb_type == spitfire) &&
> -			     page_mapping_file(page) != NULL));
> +			     folio_flush_mapping(folio) != NULL));
>  #else
> -	if (page_mapping_file(page) != NULL &&
> -	    tlb_type == spitfire)
> -		__flush_icache_page(__pa(page_address(page)));
> +	if (folio_flush_mapping(folio) != NULL &&
> +	    tlb_type == spitfire) {
> +		unsigned long pfn = folio_pfn(folio)
> +		for (i = 0; i < nr; i++)
> +			__flush_icache_page((pfn + i) * PAGE_SIZE);
> +	}
>  #endif
>  }
>  
> -void smp_flush_dcache_page_impl(struct page *page, int cpu)
> +void smp_flush_dcache_folio_impl(struct folio *folio, int cpu)
>  {
>  	int this_cpu;
>  
> @@ -948,14 +954,14 @@ void smp_flush_dcache_page_impl(struct page *page, int cpu)
>  	this_cpu = get_cpu();
>  
>  	if (cpu == this_cpu) {
> -		__local_flush_dcache_page(page);
> +		__local_flush_dcache_folio(folio);
>  	} else if (cpu_online(cpu)) {
> -		void *pg_addr = page_address(page);
> +		void *pg_addr = folio_address(folio);
>  		u64 data0 = 0;
>  
>  		if (tlb_type == spitfire) {
>  			data0 = ((u64)&xcall_flush_dcache_page_spitfire);
> -			if (page_mapping_file(page) != NULL)
> +			if (folio_flush_mapping(folio) != NULL)
>  				data0 |= ((u64)1 << 32);
>  		} else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
>  #ifdef DCACHE_ALIASING_POSSIBLE
> @@ -963,18 +969,23 @@ void smp_flush_dcache_page_impl(struct page *page, int cpu)
>  #endif
>  		}
>  		if (data0) {
> -			xcall_deliver(data0, __pa(pg_addr),
> -				      (u64) pg_addr, cpumask_of(cpu));
> +			unsigned int i, nr = folio_nr_pages(folio);
> +
> +			for (i = 0; i < nr; i++) {
> +				xcall_deliver(data0, __pa(pg_addr),
> +					      (u64) pg_addr, cpumask_of(cpu));
>  #ifdef CONFIG_DEBUG_DCFLUSH
> -			atomic_inc(&dcpage_flushes_xcall);
> +				atomic_inc(&dcpage_flushes_xcall);
>  #endif
> +				pg_addr += PAGE_SIZE;
> +			}
>  		}
>  	}
>  
>  	put_cpu();
>  }
>  
> -void flush_dcache_page_all(struct mm_struct *mm, struct page *page)
> +void flush_dcache_folio_all(struct mm_struct *mm, struct folio *folio)
>  {
>  	void *pg_addr;
>  	u64 data0;
> @@ -988,10 +999,10 @@ void flush_dcache_page_all(struct mm_struct *mm, struct page *page)
>  	atomic_inc(&dcpage_flushes);
>  #endif
>  	data0 = 0;
> -	pg_addr = page_address(page);
> +	pg_addr = folio_address(folio);
>  	if (tlb_type == spitfire) {
>  		data0 = ((u64)&xcall_flush_dcache_page_spitfire);
> -		if (page_mapping_file(page) != NULL)
> +		if (folio_flush_mapping(folio) != NULL)
>  			data0 |= ((u64)1 << 32);
>  	} else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
>  #ifdef DCACHE_ALIASING_POSSIBLE
> @@ -999,13 +1010,18 @@ void flush_dcache_page_all(struct mm_struct *mm, struct page *page)
>  #endif
>  	}
>  	if (data0) {
> -		xcall_deliver(data0, __pa(pg_addr),
> -			      (u64) pg_addr, cpu_online_mask);
> +		unsigned int i, nr = folio_nr_pages(folio);
> +
> +		for (i = 0; i < nr; i++) {
> +			xcall_deliver(data0, __pa(pg_addr),
> +				      (u64) pg_addr, cpu_online_mask);
>  #ifdef CONFIG_DEBUG_DCFLUSH
> -		atomic_inc(&dcpage_flushes_xcall);
> +			atomic_inc(&dcpage_flushes_xcall);
>  #endif
> +			pg_addr += PAGE_SIZE;
> +		}
>  	}
> -	__local_flush_dcache_page(page);
> +	__local_flush_dcache_folio(folio);
>  
>  	preempt_enable();
>  }
> diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
> index 04f9db0c3111..ab9aacbaf43c 100644
> --- a/arch/sparc/mm/init_64.c
> +++ b/arch/sparc/mm/init_64.c
> @@ -195,21 +195,26 @@ atomic_t dcpage_flushes_xcall = ATOMIC_INIT(0);
>  #endif
>  #endif
>  
> -inline void flush_dcache_page_impl(struct page *page)
> +inline void flush_dcache_folio_impl(struct folio *folio)
>  {
> +	unsigned int i, nr = folio_nr_pages(folio);
> +
>  	BUG_ON(tlb_type == hypervisor);
>  #ifdef CONFIG_DEBUG_DCFLUSH
>  	atomic_inc(&dcpage_flushes);
>  #endif
>  
>  #ifdef DCACHE_ALIASING_POSSIBLE
> -	__flush_dcache_page(page_address(page),
> -			    ((tlb_type == spitfire) &&
> -			     page_mapping_file(page) != NULL));
> +	for (i = 0; i < nr; i++)
> +		__flush_dcache_page(folio_address(folio) + i * PAGE_SIZE,
> +				    ((tlb_type == spitfire) &&
> +				     folio_flush_mapping(folio) != NULL));
>  #else
> -	if (page_mapping_file(page) != NULL &&
> -	    tlb_type == spitfire)
> -		__flush_icache_page(__pa(page_address(page)));
> +	if (folio_flush_mapping(folio) != NULL &&
> +	    tlb_type == spitfire) {
> +		for (i = 0; i < nr; i++)
> +			__flush_icache_page((pfn + i) * PAGE_SIZE);
> +	}
>  #endif
>  }
>  
> @@ -218,10 +223,10 @@ inline void flush_dcache_page_impl(struct page *page)
>  #define PG_dcache_cpu_mask	\
>  	((1UL<<ilog2(roundup_pow_of_two(NR_CPUS)))-1UL)
>  
> -#define dcache_dirty_cpu(page) \
> -	(((page)->flags >> PG_dcache_cpu_shift) & PG_dcache_cpu_mask)
> +#define dcache_dirty_cpu(folio) \
> +	(((folio)->flags >> PG_dcache_cpu_shift) & PG_dcache_cpu_mask)
>  
> -static inline void set_dcache_dirty(struct page *page, int this_cpu)
> +static inline void set_dcache_dirty(struct folio *folio, int this_cpu)
>  {
>  	unsigned long mask = this_cpu;
>  	unsigned long non_cpu_bits;
> @@ -238,11 +243,11 @@ static inline void set_dcache_dirty(struct page *page, int this_cpu)
>  			     "bne,pn	%%xcc, 1b\n\t"
>  			     " nop"
>  			     : /* no outputs */
> -			     : "r" (mask), "r" (non_cpu_bits), "r" (&page->flags)
> +			     : "r" (mask), "r" (non_cpu_bits), "r" (&folio->flags)
>  			     : "g1", "g7");
>  }
>  
> -static inline void clear_dcache_dirty_cpu(struct page *page, unsigned long cpu)
> +static inline void clear_dcache_dirty_cpu(struct folio *folio, unsigned long cpu)
>  {
>  	unsigned long mask = (1UL << PG_dcache_dirty);
>  
> @@ -260,7 +265,7 @@ static inline void clear_dcache_dirty_cpu(struct page *page, unsigned long cpu)
>  			     " nop\n"
>  			     "2:"
>  			     : /* no outputs */
> -			     : "r" (cpu), "r" (mask), "r" (&page->flags),
> +			     : "r" (cpu), "r" (mask), "r" (&folio->flags),
>  			       "i" (PG_dcache_cpu_mask),
>  			       "i" (PG_dcache_cpu_shift)
>  			     : "g1", "g7");
> @@ -284,9 +289,10 @@ static void flush_dcache(unsigned long pfn)
>  
>  	page = pfn_to_page(pfn);
>  	if (page) {
> +		struct folio *folio = page_folio(page);
>  		unsigned long pg_flags;
>  
> -		pg_flags = page->flags;
> +		pg_flags = folio->flags;
>  		if (pg_flags & (1UL << PG_dcache_dirty)) {
>  			int cpu = ((pg_flags >> PG_dcache_cpu_shift) &
>  				   PG_dcache_cpu_mask);
> @@ -296,11 +302,11 @@ static void flush_dcache(unsigned long pfn)
>  			 * in the SMP case.
>  			 */
>  			if (cpu == this_cpu)
> -				flush_dcache_page_impl(page);
> +				flush_dcache_folio_impl(folio);
>  			else
> -				smp_flush_dcache_page_impl(page, cpu);
> +				smp_flush_dcache_folio_impl(folio, cpu);
>  
> -			clear_dcache_dirty_cpu(page, cpu);
> +			clear_dcache_dirty_cpu(folio, cpu);
>  
>  			put_cpu();
>  		}
> @@ -388,12 +394,14 @@ bool __init arch_hugetlb_valid_size(unsigned long size)
>  }
>  #endif	/* CONFIG_HUGETLB_PAGE */
>  
> -void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
> +void update_mmu_cache_range(struct vm_area_struct *vma, unsigned long address,
> +		pte_t *ptep, unsigned int nr)
>  {
>  	struct mm_struct *mm;
>  	unsigned long flags;
>  	bool is_huge_tsb;
>  	pte_t pte = *ptep;
> +	unsigned int i;
>  
>  	if (tlb_type != hypervisor) {
>  		unsigned long pfn = pte_pfn(pte);
> @@ -440,15 +448,21 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *
>  		}
>  	}
>  #endif
> -	if (!is_huge_tsb)
> -		__update_mmu_tsb_insert(mm, MM_TSB_BASE, PAGE_SHIFT,
> -					address, pte_val(pte));
> +	if (!is_huge_tsb) {
> +		for (i = 0; i < nr; i++) {
> +			__update_mmu_tsb_insert(mm, MM_TSB_BASE, PAGE_SHIFT,
> +						address, pte_val(pte));
> +			address += PAGE_SIZE;
> +			pte_val(pte) += PAGE_SIZE;
> +		}
> +	}
>  
>  	spin_unlock_irqrestore(&mm->context.lock, flags);
>  }
>  
> -void flush_dcache_page(struct page *page)
> +void flush_dcache_folio(struct folio *folio)
>  {
> +	unsigned long pfn = folio_pfn(folio);
>  	struct address_space *mapping;
>  	int this_cpu;
>  
> @@ -459,35 +473,35 @@ void flush_dcache_page(struct page *page)
>  	 * is merely the zero page.  The 'bigcore' testcase in GDB
>  	 * causes this case to run millions of times.
>  	 */
> -	if (page == ZERO_PAGE(0))
> +	if (is_zero_pfn(pfn))
>  		return;
>  
>  	this_cpu = get_cpu();
>  
> -	mapping = page_mapping_file(page);
> +	mapping = folio_flush_mapping(folio);
>  	if (mapping && !mapping_mapped(mapping)) {
> -		int dirty = test_bit(PG_dcache_dirty, &page->flags);
> +		bool dirty = test_bit(PG_dcache_dirty, &folio->flags);
>  		if (dirty) {
> -			int dirty_cpu = dcache_dirty_cpu(page);
> +			int dirty_cpu = dcache_dirty_cpu(folio);
>  
>  			if (dirty_cpu == this_cpu)
>  				goto out;
> -			smp_flush_dcache_page_impl(page, dirty_cpu);
> +			smp_flush_dcache_folio_impl(folio, dirty_cpu);
>  		}
> -		set_dcache_dirty(page, this_cpu);
> +		set_dcache_dirty(folio, this_cpu);
>  	} else {
>  		/* We could delay the flush for the !page_mapping
>  		 * case too.  But that case is for exec env/arg
>  		 * pages and those are %99 certainly going to get
>  		 * faulted into the tlb (and thus flushed) anyways.
>  		 */
> -		flush_dcache_page_impl(page);
> +		flush_dcache_folio_impl(folio);
>  	}
>  
>  out:
>  	put_cpu();
>  }
> -EXPORT_SYMBOL(flush_dcache_page);
> +EXPORT_SYMBOL(flush_dcache_folio);
>  
>  void __kprobes flush_icache_range(unsigned long start, unsigned long end)
>  {
> @@ -2280,10 +2294,10 @@ void __init paging_init(void)
>  	setup_page_offset();
>  
>  	/* These build time checkes make sure that the dcache_dirty_cpu()
> -	 * page->flags usage will work.
> +	 * folio->flags usage will work.
>  	 *
>  	 * When a page gets marked as dcache-dirty, we store the
> -	 * cpu number starting at bit 32 in the page->flags.  Also,
> +	 * cpu number starting at bit 32 in the folio->flags.  Also,
>  	 * functions like clear_dcache_dirty_cpu use the cpu mask
>  	 * in 13-bit signed-immediate instruction fields.
>  	 */
> diff --git a/arch/sparc/mm/tlb.c b/arch/sparc/mm/tlb.c
> index 9a725547578e..3fa6a070912d 100644
> --- a/arch/sparc/mm/tlb.c
> +++ b/arch/sparc/mm/tlb.c
> @@ -118,6 +118,7 @@ void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr,
>  		unsigned long paddr, pfn = pte_pfn(orig);
>  		struct address_space *mapping;
>  		struct page *page;
> +		struct folio *folio;
>  
>  		if (!pfn_valid(pfn))
>  			goto no_cache_flush;
> @@ -127,13 +128,13 @@ void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr,
>  			goto no_cache_flush;
>  
>  		/* A real file page? */
> -		mapping = page_mapping_file(page);
> +		mapping = folio_flush_mapping(folio);
>  		if (!mapping)
>  			goto no_cache_flush;
>  
>  		paddr = (unsigned long) page_address(page);
>  		if ((paddr ^ vaddr) & (1 << 13))
> -			flush_dcache_page_all(mm, page);
> +			flush_dcache_folio_all(mm, folio);
>  	}
>  
>  no_cache_flush:
> -- 
> 2.39.2
> 
> 

-- 
Sincerely yours,
Mike.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v4 25/36] sparc64: Implement the new page table range API
  2023-03-15  5:14 ` [PATCH v4 25/36] sparc64: " Matthew Wilcox (Oracle)
  2023-03-15 10:11   ` Mike Rapoport
@ 2025-08-03 12:05   ` John Paul Adrian Glaubitz
  2025-08-03 19:08     ` Anthony Yznaga
  1 sibling, 1 reply; 11+ messages in thread
From: John Paul Adrian Glaubitz @ 2025-08-03 12:05 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle), linux-arch
  Cc: linux-mm, linux-kernel, David S. Miller, sparclinux,
	Andreas Larsson, Rod Schnell, Sam James, Anthony Yznaga

Hi Matthew,

On Wed, 2023-03-15 at 05:14 +0000, Matthew Wilcox (Oracle) wrote:
> Add set_ptes(), update_mmu_cache_range(), flush_dcache_folio() and
> flush_icache_pages().  Convert the PG_dcache_dirty flag from being
> per-page to per-folio.
> 
> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: sparclinux@vger.kernel.org
> ---
>  arch/sparc/include/asm/cacheflush_64.h | 18 ++++--
>  arch/sparc/include/asm/pgtable_64.h    | 24 ++++++--
>  arch/sparc/kernel/smp_64.c             | 56 +++++++++++-------
>  arch/sparc/mm/init_64.c                | 78 +++++++++++++++-----------
>  arch/sparc/mm/tlb.c                    |  5 +-
>  5 files changed, 116 insertions(+), 65 deletions(-)
> 
> diff --git a/arch/sparc/include/asm/cacheflush_64.h b/arch/sparc/include/asm/cacheflush_64.h
> index b9341836597e..a9a719f04d06 100644
> --- a/arch/sparc/include/asm/cacheflush_64.h
> +++ b/arch/sparc/include/asm/cacheflush_64.h
> @@ -35,20 +35,26 @@ void flush_icache_range(unsigned long start, unsigned long end);
>  void __flush_icache_page(unsigned long);
>  
>  void __flush_dcache_page(void *addr, int flush_icache);
> -void flush_dcache_page_impl(struct page *page);
> +void flush_dcache_folio_impl(struct folio *folio);
>  #ifdef CONFIG_SMP
> -void smp_flush_dcache_page_impl(struct page *page, int cpu);
> -void flush_dcache_page_all(struct mm_struct *mm, struct page *page);
> +void smp_flush_dcache_folio_impl(struct folio *folio, int cpu);
> +void flush_dcache_folio_all(struct mm_struct *mm, struct folio *folio);
>  #else
> -#define smp_flush_dcache_page_impl(page,cpu) flush_dcache_page_impl(page)
> -#define flush_dcache_page_all(mm,page) flush_dcache_page_impl(page)
> +#define smp_flush_dcache_folio_impl(folio, cpu) flush_dcache_folio_impl(folio)
> +#define flush_dcache_folio_all(mm, folio) flush_dcache_folio_impl(folio)
>  #endif
>  
>  void __flush_dcache_range(unsigned long start, unsigned long end);
>  #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
> -void flush_dcache_page(struct page *page);
> +void flush_dcache_folio(struct folio *folio);
> +#define flush_dcache_folio flush_dcache_folio
> +static inline void flush_dcache_page(struct page *page)
> +{
> +	flush_dcache_folio(page_folio(page));
> +}
>  
>  #define flush_icache_page(vma, pg)	do { } while(0)
> +#define flush_icache_pages(vma, pg, nr)	do { } while(0)
>  
>  void flush_ptrace_access(struct vm_area_struct *, struct page *,
>  			 unsigned long uaddr, void *kaddr,
> diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
> index 2dc8d4641734..49c37000e1b1 100644
> --- a/arch/sparc/include/asm/pgtable_64.h
> +++ b/arch/sparc/include/asm/pgtable_64.h
> @@ -911,8 +911,19 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
>  	maybe_tlb_batch_add(mm, addr, ptep, orig, fullmm, PAGE_SHIFT);
>  }
>  
> -#define set_pte_at(mm,addr,ptep,pte)	\
> -	__set_pte_at((mm), (addr), (ptep), (pte), 0)
> +static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
> +		pte_t *ptep, pte_t pte, unsigned int nr)
> +{
> +	for (;;) {
> +		__set_pte_at(mm, addr, ptep, pte, 0);
> +		if (--nr == 0)
> +			break;
> +		ptep++;
> +		pte_val(pte) += PAGE_SIZE;
> +		addr += PAGE_SIZE;
> +	}
> +}
> +#define set_ptes set_ptes
>  
>  #define pte_clear(mm,addr,ptep)		\
>  	set_pte_at((mm), (addr), (ptep), __pte(0UL))
> @@ -931,8 +942,8 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
>  									\
>  		if (pfn_valid(this_pfn) &&				\
>  		    (((old_addr) ^ (new_addr)) & (1 << 13)))		\
> -			flush_dcache_page_all(current->mm,		\
> -					      pfn_to_page(this_pfn));	\
> +			flush_dcache_folio_all(current->mm,		\
> +				page_folio(pfn_to_page(this_pfn)));	\
>  	}								\
>  	newpte;								\
>  })
> @@ -947,7 +958,10 @@ struct seq_file;
>  void mmu_info(struct seq_file *);
>  
>  struct vm_area_struct;
> -void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t *);
> +void update_mmu_cache_range(struct vm_area_struct *, unsigned long addr,
> +		pte_t *ptep, unsigned int nr);
> +#define update_mmu_cache(vma, addr, ptep) \
> +	update_mmu_cache_range(vma, addr, ptep, 1)
>  #ifdef CONFIG_TRANSPARENT_HUGEPAGE
>  void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr,
>  			  pmd_t *pmd);
> diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
> index a55295d1b924..90ef8677ac89 100644
> --- a/arch/sparc/kernel/smp_64.c
> +++ b/arch/sparc/kernel/smp_64.c
> @@ -921,20 +921,26 @@ extern unsigned long xcall_flush_dcache_page_cheetah;
>  #endif
>  extern unsigned long xcall_flush_dcache_page_spitfire;
>  
> -static inline void __local_flush_dcache_page(struct page *page)
> +static inline void __local_flush_dcache_folio(struct folio *folio)
>  {
> +	unsigned int i, nr = folio_nr_pages(folio);
> +
>  #ifdef DCACHE_ALIASING_POSSIBLE
> -	__flush_dcache_page(page_address(page),
> +	for (i = 0; i < nr; i++)
> +		__flush_dcache_page(folio_address(folio) + i * PAGE_SIZE,
>  			    ((tlb_type == spitfire) &&
> -			     page_mapping_file(page) != NULL));
> +			     folio_flush_mapping(folio) != NULL));
>  #else
> -	if (page_mapping_file(page) != NULL &&
> -	    tlb_type == spitfire)
> -		__flush_icache_page(__pa(page_address(page)));
> +	if (folio_flush_mapping(folio) != NULL &&
> +	    tlb_type == spitfire) {
> +		unsigned long pfn = folio_pfn(folio)
> +		for (i = 0; i < nr; i++)
> +			__flush_icache_page((pfn + i) * PAGE_SIZE);
> +	}
>  #endif
>  }
>  
> -void smp_flush_dcache_page_impl(struct page *page, int cpu)
> +void smp_flush_dcache_folio_impl(struct folio *folio, int cpu)
>  {
>  	int this_cpu;
>  
> @@ -948,14 +954,14 @@ void smp_flush_dcache_page_impl(struct page *page, int cpu)
>  	this_cpu = get_cpu();
>  
>  	if (cpu == this_cpu) {
> -		__local_flush_dcache_page(page);
> +		__local_flush_dcache_folio(folio);
>  	} else if (cpu_online(cpu)) {
> -		void *pg_addr = page_address(page);
> +		void *pg_addr = folio_address(folio);
>  		u64 data0 = 0;
>  
>  		if (tlb_type == spitfire) {
>  			data0 = ((u64)&xcall_flush_dcache_page_spitfire);
> -			if (page_mapping_file(page) != NULL)
> +			if (folio_flush_mapping(folio) != NULL)
>  				data0 |= ((u64)1 << 32);
>  		} else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
>  #ifdef DCACHE_ALIASING_POSSIBLE
> @@ -963,18 +969,23 @@ void smp_flush_dcache_page_impl(struct page *page, int cpu)
>  #endif
>  		}
>  		if (data0) {
> -			xcall_deliver(data0, __pa(pg_addr),
> -				      (u64) pg_addr, cpumask_of(cpu));
> +			unsigned int i, nr = folio_nr_pages(folio);
> +
> +			for (i = 0; i < nr; i++) {
> +				xcall_deliver(data0, __pa(pg_addr),
> +					      (u64) pg_addr, cpumask_of(cpu));
>  #ifdef CONFIG_DEBUG_DCFLUSH
> -			atomic_inc(&dcpage_flushes_xcall);
> +				atomic_inc(&dcpage_flushes_xcall);
>  #endif
> +				pg_addr += PAGE_SIZE;
> +			}
>  		}
>  	}
>  
>  	put_cpu();
>  }
>  
> -void flush_dcache_page_all(struct mm_struct *mm, struct page *page)
> +void flush_dcache_folio_all(struct mm_struct *mm, struct folio *folio)
>  {
>  	void *pg_addr;
>  	u64 data0;
> @@ -988,10 +999,10 @@ void flush_dcache_page_all(struct mm_struct *mm, struct page *page)
>  	atomic_inc(&dcpage_flushes);
>  #endif
>  	data0 = 0;
> -	pg_addr = page_address(page);
> +	pg_addr = folio_address(folio);
>  	if (tlb_type == spitfire) {
>  		data0 = ((u64)&xcall_flush_dcache_page_spitfire);
> -		if (page_mapping_file(page) != NULL)
> +		if (folio_flush_mapping(folio) != NULL)
>  			data0 |= ((u64)1 << 32);
>  	} else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
>  #ifdef DCACHE_ALIASING_POSSIBLE
> @@ -999,13 +1010,18 @@ void flush_dcache_page_all(struct mm_struct *mm, struct page *page)
>  #endif
>  	}
>  	if (data0) {
> -		xcall_deliver(data0, __pa(pg_addr),
> -			      (u64) pg_addr, cpu_online_mask);
> +		unsigned int i, nr = folio_nr_pages(folio);
> +
> +		for (i = 0; i < nr; i++) {
> +			xcall_deliver(data0, __pa(pg_addr),
> +				      (u64) pg_addr, cpu_online_mask);
>  #ifdef CONFIG_DEBUG_DCFLUSH
> -		atomic_inc(&dcpage_flushes_xcall);
> +			atomic_inc(&dcpage_flushes_xcall);
>  #endif
> +			pg_addr += PAGE_SIZE;
> +		}
>  	}
> -	__local_flush_dcache_page(page);
> +	__local_flush_dcache_folio(folio);
>  
>  	preempt_enable();
>  }
> diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
> index 04f9db0c3111..ab9aacbaf43c 100644
> --- a/arch/sparc/mm/init_64.c
> +++ b/arch/sparc/mm/init_64.c
> @@ -195,21 +195,26 @@ atomic_t dcpage_flushes_xcall = ATOMIC_INIT(0);
>  #endif
>  #endif
>  
> -inline void flush_dcache_page_impl(struct page *page)
> +inline void flush_dcache_folio_impl(struct folio *folio)
>  {
> +	unsigned int i, nr = folio_nr_pages(folio);
> +
>  	BUG_ON(tlb_type == hypervisor);
>  #ifdef CONFIG_DEBUG_DCFLUSH
>  	atomic_inc(&dcpage_flushes);
>  #endif
>  
>  #ifdef DCACHE_ALIASING_POSSIBLE
> -	__flush_dcache_page(page_address(page),
> -			    ((tlb_type == spitfire) &&
> -			     page_mapping_file(page) != NULL));
> +	for (i = 0; i < nr; i++)
> +		__flush_dcache_page(folio_address(folio) + i * PAGE_SIZE,
> +				    ((tlb_type == spitfire) &&
> +				     folio_flush_mapping(folio) != NULL));
>  #else
> -	if (page_mapping_file(page) != NULL &&
> -	    tlb_type == spitfire)
> -		__flush_icache_page(__pa(page_address(page)));
> +	if (folio_flush_mapping(folio) != NULL &&
> +	    tlb_type == spitfire) {
> +		for (i = 0; i < nr; i++)
> +			__flush_icache_page((pfn + i) * PAGE_SIZE);
> +	}
>  #endif
>  }
>  
> @@ -218,10 +223,10 @@ inline void flush_dcache_page_impl(struct page *page)
>  #define PG_dcache_cpu_mask	\
>  	((1UL<<ilog2(roundup_pow_of_two(NR_CPUS)))-1UL)
>  
> -#define dcache_dirty_cpu(page) \
> -	(((page)->flags >> PG_dcache_cpu_shift) & PG_dcache_cpu_mask)
> +#define dcache_dirty_cpu(folio) \
> +	(((folio)->flags >> PG_dcache_cpu_shift) & PG_dcache_cpu_mask)
>  
> -static inline void set_dcache_dirty(struct page *page, int this_cpu)
> +static inline void set_dcache_dirty(struct folio *folio, int this_cpu)
>  {
>  	unsigned long mask = this_cpu;
>  	unsigned long non_cpu_bits;
> @@ -238,11 +243,11 @@ static inline void set_dcache_dirty(struct page *page, int this_cpu)
>  			     "bne,pn	%%xcc, 1b\n\t"
>  			     " nop"
>  			     : /* no outputs */
> -			     : "r" (mask), "r" (non_cpu_bits), "r" (&page->flags)
> +			     : "r" (mask), "r" (non_cpu_bits), "r" (&folio->flags)
>  			     : "g1", "g7");
>  }
>  
> -static inline void clear_dcache_dirty_cpu(struct page *page, unsigned long cpu)
> +static inline void clear_dcache_dirty_cpu(struct folio *folio, unsigned long cpu)
>  {
>  	unsigned long mask = (1UL << PG_dcache_dirty);
>  
> @@ -260,7 +265,7 @@ static inline void clear_dcache_dirty_cpu(struct page *page, unsigned long cpu)
>  			     " nop\n"
>  			     "2:"
>  			     : /* no outputs */
> -			     : "r" (cpu), "r" (mask), "r" (&page->flags),
> +			     : "r" (cpu), "r" (mask), "r" (&folio->flags),
>  			       "i" (PG_dcache_cpu_mask),
>  			       "i" (PG_dcache_cpu_shift)
>  			     : "g1", "g7");
> @@ -284,9 +289,10 @@ static void flush_dcache(unsigned long pfn)
>  
>  	page = pfn_to_page(pfn);
>  	if (page) {
> +		struct folio *folio = page_folio(page);
>  		unsigned long pg_flags;
>  
> -		pg_flags = page->flags;
> +		pg_flags = folio->flags;
>  		if (pg_flags & (1UL << PG_dcache_dirty)) {
>  			int cpu = ((pg_flags >> PG_dcache_cpu_shift) &
>  				   PG_dcache_cpu_mask);
> @@ -296,11 +302,11 @@ static void flush_dcache(unsigned long pfn)
>  			 * in the SMP case.
>  			 */
>  			if (cpu == this_cpu)
> -				flush_dcache_page_impl(page);
> +				flush_dcache_folio_impl(folio);
>  			else
> -				smp_flush_dcache_page_impl(page, cpu);
> +				smp_flush_dcache_folio_impl(folio, cpu);
>  
> -			clear_dcache_dirty_cpu(page, cpu);
> +			clear_dcache_dirty_cpu(folio, cpu);
>  
>  			put_cpu();
>  		}
> @@ -388,12 +394,14 @@ bool __init arch_hugetlb_valid_size(unsigned long size)
>  }
>  #endif	/* CONFIG_HUGETLB_PAGE */
>  
> -void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
> +void update_mmu_cache_range(struct vm_area_struct *vma, unsigned long address,
> +		pte_t *ptep, unsigned int nr)
>  {
>  	struct mm_struct *mm;
>  	unsigned long flags;
>  	bool is_huge_tsb;
>  	pte_t pte = *ptep;
> +	unsigned int i;
>  
>  	if (tlb_type != hypervisor) {
>  		unsigned long pfn = pte_pfn(pte);
> @@ -440,15 +448,21 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *
>  		}
>  	}
>  #endif
> -	if (!is_huge_tsb)
> -		__update_mmu_tsb_insert(mm, MM_TSB_BASE, PAGE_SHIFT,
> -					address, pte_val(pte));
> +	if (!is_huge_tsb) {
> +		for (i = 0; i < nr; i++) {
> +			__update_mmu_tsb_insert(mm, MM_TSB_BASE, PAGE_SHIFT,
> +						address, pte_val(pte));
> +			address += PAGE_SIZE;
> +			pte_val(pte) += PAGE_SIZE;
> +		}
> +	}
>  
>  	spin_unlock_irqrestore(&mm->context.lock, flags);
>  }
>  
> -void flush_dcache_page(struct page *page)
> +void flush_dcache_folio(struct folio *folio)
>  {
> +	unsigned long pfn = folio_pfn(folio);
>  	struct address_space *mapping;
>  	int this_cpu;
>  
> @@ -459,35 +473,35 @@ void flush_dcache_page(struct page *page)
>  	 * is merely the zero page.  The 'bigcore' testcase in GDB
>  	 * causes this case to run millions of times.
>  	 */
> -	if (page == ZERO_PAGE(0))
> +	if (is_zero_pfn(pfn))
>  		return;
>  
>  	this_cpu = get_cpu();
>  
> -	mapping = page_mapping_file(page);
> +	mapping = folio_flush_mapping(folio);
>  	if (mapping && !mapping_mapped(mapping)) {
> -		int dirty = test_bit(PG_dcache_dirty, &page->flags);
> +		bool dirty = test_bit(PG_dcache_dirty, &folio->flags);
>  		if (dirty) {
> -			int dirty_cpu = dcache_dirty_cpu(page);
> +			int dirty_cpu = dcache_dirty_cpu(folio);
>  
>  			if (dirty_cpu == this_cpu)
>  				goto out;
> -			smp_flush_dcache_page_impl(page, dirty_cpu);
> +			smp_flush_dcache_folio_impl(folio, dirty_cpu);
>  		}
> -		set_dcache_dirty(page, this_cpu);
> +		set_dcache_dirty(folio, this_cpu);
>  	} else {
>  		/* We could delay the flush for the !page_mapping
>  		 * case too.  But that case is for exec env/arg
>  		 * pages and those are %99 certainly going to get
>  		 * faulted into the tlb (and thus flushed) anyways.
>  		 */
> -		flush_dcache_page_impl(page);
> +		flush_dcache_folio_impl(folio);
>  	}
>  
>  out:
>  	put_cpu();
>  }
> -EXPORT_SYMBOL(flush_dcache_page);
> +EXPORT_SYMBOL(flush_dcache_folio);
>  
>  void __kprobes flush_icache_range(unsigned long start, unsigned long end)
>  {
> @@ -2280,10 +2294,10 @@ void __init paging_init(void)
>  	setup_page_offset();
>  
>  	/* These build time checkes make sure that the dcache_dirty_cpu()
> -	 * page->flags usage will work.
> +	 * folio->flags usage will work.
>  	 *
>  	 * When a page gets marked as dcache-dirty, we store the
> -	 * cpu number starting at bit 32 in the page->flags.  Also,
> +	 * cpu number starting at bit 32 in the folio->flags.  Also,
>  	 * functions like clear_dcache_dirty_cpu use the cpu mask
>  	 * in 13-bit signed-immediate instruction fields.
>  	 */
> diff --git a/arch/sparc/mm/tlb.c b/arch/sparc/mm/tlb.c
> index 9a725547578e..3fa6a070912d 100644
> --- a/arch/sparc/mm/tlb.c
> +++ b/arch/sparc/mm/tlb.c
> @@ -118,6 +118,7 @@ void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr,
>  		unsigned long paddr, pfn = pte_pfn(orig);
>  		struct address_space *mapping;
>  		struct page *page;
> +		struct folio *folio;
>  
>  		if (!pfn_valid(pfn))
>  			goto no_cache_flush;
> @@ -127,13 +128,13 @@ void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr,
>  			goto no_cache_flush;
>  
>  		/* A real file page? */
> -		mapping = page_mapping_file(page);
> +		mapping = folio_flush_mapping(folio);
>  		if (!mapping)
>  			goto no_cache_flush;
>  
>  		paddr = (unsigned long) page_address(page);
>  		if ((paddr ^ vaddr) & (1 << 13))
> -			flush_dcache_page_all(mm, page);
> +			flush_dcache_folio_all(mm, folio);
>  	}
>  
>  no_cache_flush:

This change broke the kernel on sun4u SPARC systems. This has been observed on a Sun Netra 240.

During boot, the kernel crashes with:

[   25.855163] Unable to handle kernel NULL pointer dereference
[   25.929588] tsk->{mm,active_mm}->context = 0000000000000001
[   26.002772] tsk->{mm,active_mm}->pgd = fff00000001bc000
[   26.071405]               \|/ ____ \|/
[   26.071405]               "@'/ .. \`@"
[   26.071405]               /_| \__/ |_\
[   26.071405]                  \__U_/
[   26.264705] modprobe(33): Oops [#1]
[   26.310445] CPU: 0 PID: 33 Comm: modprobe Not tainted 6.5.0-rc4+ #16
[   26.393937] TSTATE: 0000004411001601 TPC: 0000000000452a28 TNPC: 0000000000452a2c Y: 00000008    Not tainted
[   26.523184] TPC: <tlb_batch_add+0x108/0x1a0>
[   26.579221] g0: ace36c1f2cee4067 g1: 0000000000000028 g2: 00000000000a010c g3: 000c000000000000
[   26.693607] g4: fff0000001947000 g5: 0000000000000000 g6: fff0000001948000 g7: fff000023fe33f00
[   26.807978] o0: fff000000738fff8 o1: 000007feffffe000 o2: fff000000194b788 o3: 0000000000e3c038
[   26.922356] o4: ffffffffffffffff o5: 0000000000e3c038 sp: fff000000194aee1 ret_pc: 000000000065d194
[   27.041302] RPC: <__pte_offset_map_lock+0x14/0x60>
[   27.104203] l0: fff000000194b860 l1: 0000000000000001 l2: 0000000000000000 l3: fff000000194b850
[   27.218583] l4: 0000000000002000 l5: 00000000001010f8 l6: 0000000000000002 l7: 0000000000000040
[   27.332959] i0: fff000000194e400 i1: 000007feffffe000 i2: 000c000004857588 i3: 80000002026d3fb2
[   27.447334] i4: 0000000000000000 i5: 000000000000000d i6: fff000000194af91 i7: 0000000000659110
[   27.561709] I7: <change_protection+0x910/0xe00>
[   27.621178] Call Trace:
[   27.653202] [<0000000000659110>] change_protection+0x910/0xe00
[   27.729838] [<00000000006596f4>] mprotect_fixup+0xf4/0x2c0
[   27.801892] [<00000000006c754c>] setup_arg_pages+0x12c/0x2c0
[   27.876237] [<0000000000737d80>] load_elf_binary+0x360/0x1380
[   27.951722] [<00000000006c8564>] bprm_execve+0x1e4/0x560
[   28.021493] [<00000000006c8e8c>] kernel_execve+0x14c/0x200
[   28.093548] [<000000000047f6e8>] call_usermodehelper_exec_async+0xa8/0x140
[   28.183906] [<0000000000405fc8>] ret_from_fork+0x1c/0x2c
[   28.253672] [<0000000000000000>] 0x0
[   28.300568] Disabling lock debugging due to kernel taint
[   28.370336] Caller[0000000000659110]: change_protection+0x910/0xe00
[   28.452686] Caller[00000000006596f4]: mprotect_fixup+0xf4/0x2c0
[   28.530461] Caller[00000000006c754c]: setup_arg_pages+0x12c/0x2c0
[   28.610524] Caller[0000000000737d80]: load_elf_binary+0x360/0x1380
[   28.691730] Caller[00000000006c8564]: bprm_execve+0x1e4/0x560
[   28.767218] Caller[00000000006c8e8c]: kernel_execve+0x14c/0x200
[   28.844993] Caller[000000000047f6e8]: call_usermodehelper_exec_async+0xa8/0x140
[   28.941071] Caller[0000000000405fc8]: ret_from_fork+0x1c/0x2c
[   29.016554] Caller[0000000000000000]: 0x0
[   29.069167] Instruction DUMP:
[   29.069169]  80886001 
[   29.108052]  126fffc8 
[   29.138932]  01000000 
[   29.169815] <c2582000>
[   29.200697]  83307013 
[   29.231578]  80886001 
[   29.262458]  02680007 
[   29.293338]  01000000 
[   29.324223]  c2582000 
[   29.355102]

This crash is not observed on sun4v systems.

Any idea what could be the fix?

Adrian

-- 
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer
`. `'   Physicist
  `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v4 25/36] sparc64: Implement the new page table range API
  2025-08-03 12:05   ` John Paul Adrian Glaubitz
@ 2025-08-03 19:08     ` Anthony Yznaga
  2025-08-04  5:12       ` John Paul Adrian Glaubitz
  0 siblings, 1 reply; 11+ messages in thread
From: Anthony Yznaga @ 2025-08-03 19:08 UTC (permalink / raw)
  To: John Paul Adrian Glaubitz, Matthew Wilcox (Oracle), linux-arch
  Cc: linux-mm, linux-kernel, David S. Miller, sparclinux,
	Andreas Larsson, Rod Schnell, Sam James

Hi Adrian,

On 8/3/25 5:05 AM, John Paul Adrian Glaubitz wrote:
> Hi Matthew,
> 
> On Wed, 2023-03-15 at 05:14 +0000, Matthew Wilcox (Oracle) wrote:
>> Add set_ptes(), update_mmu_cache_range(), flush_dcache_folio() and
>> flush_icache_pages().  Convert the PG_dcache_dirty flag from being
>> per-page to per-folio.
>>
>> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
>> Cc: "David S. Miller" <davem@davemloft.net>
>> Cc: sparclinux@vger.kernel.org
>> ---
>>   arch/sparc/include/asm/cacheflush_64.h | 18 ++++--
>>   arch/sparc/include/asm/pgtable_64.h    | 24 ++++++--
>>   arch/sparc/kernel/smp_64.c             | 56 +++++++++++-------
>>   arch/sparc/mm/init_64.c                | 78 +++++++++++++++-----------
>>   arch/sparc/mm/tlb.c                    |  5 +-
>>   5 files changed, 116 insertions(+), 65 deletions(-)
>>
>> diff --git a/arch/sparc/include/asm/cacheflush_64.h b/arch/sparc/include/asm/cacheflush_64.h
>> index b9341836597e..a9a719f04d06 100644
>> --- a/arch/sparc/include/asm/cacheflush_64.h
>> +++ b/arch/sparc/include/asm/cacheflush_64.h
>> @@ -35,20 +35,26 @@ void flush_icache_range(unsigned long start, unsigned long end);
>>   void __flush_icache_page(unsigned long);
>>   
>>   void __flush_dcache_page(void *addr, int flush_icache);
>> -void flush_dcache_page_impl(struct page *page);
>> +void flush_dcache_folio_impl(struct folio *folio);
>>   #ifdef CONFIG_SMP
>> -void smp_flush_dcache_page_impl(struct page *page, int cpu);
>> -void flush_dcache_page_all(struct mm_struct *mm, struct page *page);
>> +void smp_flush_dcache_folio_impl(struct folio *folio, int cpu);
>> +void flush_dcache_folio_all(struct mm_struct *mm, struct folio *folio);
>>   #else
>> -#define smp_flush_dcache_page_impl(page,cpu) flush_dcache_page_impl(page)
>> -#define flush_dcache_page_all(mm,page) flush_dcache_page_impl(page)
>> +#define smp_flush_dcache_folio_impl(folio, cpu) flush_dcache_folio_impl(folio)
>> +#define flush_dcache_folio_all(mm, folio) flush_dcache_folio_impl(folio)
>>   #endif
>>   
>>   void __flush_dcache_range(unsigned long start, unsigned long end);
>>   #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
>> -void flush_dcache_page(struct page *page);
>> +void flush_dcache_folio(struct folio *folio);
>> +#define flush_dcache_folio flush_dcache_folio
>> +static inline void flush_dcache_page(struct page *page)
>> +{
>> +	flush_dcache_folio(page_folio(page));
>> +}
>>   
>>   #define flush_icache_page(vma, pg)	do { } while(0)
>> +#define flush_icache_pages(vma, pg, nr)	do { } while(0)
>>   
>>   void flush_ptrace_access(struct vm_area_struct *, struct page *,
>>   			 unsigned long uaddr, void *kaddr,
>> diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
>> index 2dc8d4641734..49c37000e1b1 100644
>> --- a/arch/sparc/include/asm/pgtable_64.h
>> +++ b/arch/sparc/include/asm/pgtable_64.h
>> @@ -911,8 +911,19 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
>>   	maybe_tlb_batch_add(mm, addr, ptep, orig, fullmm, PAGE_SHIFT);
>>   }
>>   
>> -#define set_pte_at(mm,addr,ptep,pte)	\
>> -	__set_pte_at((mm), (addr), (ptep), (pte), 0)
>> +static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
>> +		pte_t *ptep, pte_t pte, unsigned int nr)
>> +{
>> +	for (;;) {
>> +		__set_pte_at(mm, addr, ptep, pte, 0);
>> +		if (--nr == 0)
>> +			break;
>> +		ptep++;
>> +		pte_val(pte) += PAGE_SIZE;
>> +		addr += PAGE_SIZE;
>> +	}
>> +}
>> +#define set_ptes set_ptes
>>   
>>   #define pte_clear(mm,addr,ptep)		\
>>   	set_pte_at((mm), (addr), (ptep), __pte(0UL))
>> @@ -931,8 +942,8 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
>>   									\
>>   		if (pfn_valid(this_pfn) &&				\
>>   		    (((old_addr) ^ (new_addr)) & (1 << 13)))		\
>> -			flush_dcache_page_all(current->mm,		\
>> -					      pfn_to_page(this_pfn));	\
>> +			flush_dcache_folio_all(current->mm,		\
>> +				page_folio(pfn_to_page(this_pfn)));	\
>>   	}								\
>>   	newpte;								\
>>   })
>> @@ -947,7 +958,10 @@ struct seq_file;
>>   void mmu_info(struct seq_file *);
>>   
>>   struct vm_area_struct;
>> -void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t *);
>> +void update_mmu_cache_range(struct vm_area_struct *, unsigned long addr,
>> +		pte_t *ptep, unsigned int nr);
>> +#define update_mmu_cache(vma, addr, ptep) \
>> +	update_mmu_cache_range(vma, addr, ptep, 1)
>>   #ifdef CONFIG_TRANSPARENT_HUGEPAGE
>>   void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr,
>>   			  pmd_t *pmd);
>> diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
>> index a55295d1b924..90ef8677ac89 100644
>> --- a/arch/sparc/kernel/smp_64.c
>> +++ b/arch/sparc/kernel/smp_64.c
>> @@ -921,20 +921,26 @@ extern unsigned long xcall_flush_dcache_page_cheetah;
>>   #endif
>>   extern unsigned long xcall_flush_dcache_page_spitfire;
>>   
>> -static inline void __local_flush_dcache_page(struct page *page)
>> +static inline void __local_flush_dcache_folio(struct folio *folio)
>>   {
>> +	unsigned int i, nr = folio_nr_pages(folio);
>> +
>>   #ifdef DCACHE_ALIASING_POSSIBLE
>> -	__flush_dcache_page(page_address(page),
>> +	for (i = 0; i < nr; i++)
>> +		__flush_dcache_page(folio_address(folio) + i * PAGE_SIZE,
>>   			    ((tlb_type == spitfire) &&
>> -			     page_mapping_file(page) != NULL));
>> +			     folio_flush_mapping(folio) != NULL));
>>   #else
>> -	if (page_mapping_file(page) != NULL &&
>> -	    tlb_type == spitfire)
>> -		__flush_icache_page(__pa(page_address(page)));
>> +	if (folio_flush_mapping(folio) != NULL &&
>> +	    tlb_type == spitfire) {
>> +		unsigned long pfn = folio_pfn(folio)
>> +		for (i = 0; i < nr; i++)
>> +			__flush_icache_page((pfn + i) * PAGE_SIZE);
>> +	}
>>   #endif
>>   }
>>   
>> -void smp_flush_dcache_page_impl(struct page *page, int cpu)
>> +void smp_flush_dcache_folio_impl(struct folio *folio, int cpu)
>>   {
>>   	int this_cpu;
>>   
>> @@ -948,14 +954,14 @@ void smp_flush_dcache_page_impl(struct page *page, int cpu)
>>   	this_cpu = get_cpu();
>>   
>>   	if (cpu == this_cpu) {
>> -		__local_flush_dcache_page(page);
>> +		__local_flush_dcache_folio(folio);
>>   	} else if (cpu_online(cpu)) {
>> -		void *pg_addr = page_address(page);
>> +		void *pg_addr = folio_address(folio);
>>   		u64 data0 = 0;
>>   
>>   		if (tlb_type == spitfire) {
>>   			data0 = ((u64)&xcall_flush_dcache_page_spitfire);
>> -			if (page_mapping_file(page) != NULL)
>> +			if (folio_flush_mapping(folio) != NULL)
>>   				data0 |= ((u64)1 << 32);
>>   		} else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
>>   #ifdef DCACHE_ALIASING_POSSIBLE
>> @@ -963,18 +969,23 @@ void smp_flush_dcache_page_impl(struct page *page, int cpu)
>>   #endif
>>   		}
>>   		if (data0) {
>> -			xcall_deliver(data0, __pa(pg_addr),
>> -				      (u64) pg_addr, cpumask_of(cpu));
>> +			unsigned int i, nr = folio_nr_pages(folio);
>> +
>> +			for (i = 0; i < nr; i++) {
>> +				xcall_deliver(data0, __pa(pg_addr),
>> +					      (u64) pg_addr, cpumask_of(cpu));
>>   #ifdef CONFIG_DEBUG_DCFLUSH
>> -			atomic_inc(&dcpage_flushes_xcall);
>> +				atomic_inc(&dcpage_flushes_xcall);
>>   #endif
>> +				pg_addr += PAGE_SIZE;
>> +			}
>>   		}
>>   	}
>>   
>>   	put_cpu();
>>   }
>>   
>> -void flush_dcache_page_all(struct mm_struct *mm, struct page *page)
>> +void flush_dcache_folio_all(struct mm_struct *mm, struct folio *folio)
>>   {
>>   	void *pg_addr;
>>   	u64 data0;
>> @@ -988,10 +999,10 @@ void flush_dcache_page_all(struct mm_struct *mm, struct page *page)
>>   	atomic_inc(&dcpage_flushes);
>>   #endif
>>   	data0 = 0;
>> -	pg_addr = page_address(page);
>> +	pg_addr = folio_address(folio);
>>   	if (tlb_type == spitfire) {
>>   		data0 = ((u64)&xcall_flush_dcache_page_spitfire);
>> -		if (page_mapping_file(page) != NULL)
>> +		if (folio_flush_mapping(folio) != NULL)
>>   			data0 |= ((u64)1 << 32);
>>   	} else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
>>   #ifdef DCACHE_ALIASING_POSSIBLE
>> @@ -999,13 +1010,18 @@ void flush_dcache_page_all(struct mm_struct *mm, struct page *page)
>>   #endif
>>   	}
>>   	if (data0) {
>> -		xcall_deliver(data0, __pa(pg_addr),
>> -			      (u64) pg_addr, cpu_online_mask);
>> +		unsigned int i, nr = folio_nr_pages(folio);
>> +
>> +		for (i = 0; i < nr; i++) {
>> +			xcall_deliver(data0, __pa(pg_addr),
>> +				      (u64) pg_addr, cpu_online_mask);
>>   #ifdef CONFIG_DEBUG_DCFLUSH
>> -		atomic_inc(&dcpage_flushes_xcall);
>> +			atomic_inc(&dcpage_flushes_xcall);
>>   #endif
>> +			pg_addr += PAGE_SIZE;
>> +		}
>>   	}
>> -	__local_flush_dcache_page(page);
>> +	__local_flush_dcache_folio(folio);
>>   
>>   	preempt_enable();
>>   }
>> diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
>> index 04f9db0c3111..ab9aacbaf43c 100644
>> --- a/arch/sparc/mm/init_64.c
>> +++ b/arch/sparc/mm/init_64.c
>> @@ -195,21 +195,26 @@ atomic_t dcpage_flushes_xcall = ATOMIC_INIT(0);
>>   #endif
>>   #endif
>>   
>> -inline void flush_dcache_page_impl(struct page *page)
>> +inline void flush_dcache_folio_impl(struct folio *folio)
>>   {
>> +	unsigned int i, nr = folio_nr_pages(folio);
>> +
>>   	BUG_ON(tlb_type == hypervisor);
>>   #ifdef CONFIG_DEBUG_DCFLUSH
>>   	atomic_inc(&dcpage_flushes);
>>   #endif
>>   
>>   #ifdef DCACHE_ALIASING_POSSIBLE
>> -	__flush_dcache_page(page_address(page),
>> -			    ((tlb_type == spitfire) &&
>> -			     page_mapping_file(page) != NULL));
>> +	for (i = 0; i < nr; i++)
>> +		__flush_dcache_page(folio_address(folio) + i * PAGE_SIZE,
>> +				    ((tlb_type == spitfire) &&
>> +				     folio_flush_mapping(folio) != NULL));
>>   #else
>> -	if (page_mapping_file(page) != NULL &&
>> -	    tlb_type == spitfire)
>> -		__flush_icache_page(__pa(page_address(page)));
>> +	if (folio_flush_mapping(folio) != NULL &&
>> +	    tlb_type == spitfire) {
>> +		for (i = 0; i < nr; i++)
>> +			__flush_icache_page((pfn + i) * PAGE_SIZE);
>> +	}
>>   #endif
>>   }
>>   
>> @@ -218,10 +223,10 @@ inline void flush_dcache_page_impl(struct page *page)
>>   #define PG_dcache_cpu_mask	\
>>   	((1UL<<ilog2(roundup_pow_of_two(NR_CPUS)))-1UL)
>>   
>> -#define dcache_dirty_cpu(page) \
>> -	(((page)->flags >> PG_dcache_cpu_shift) & PG_dcache_cpu_mask)
>> +#define dcache_dirty_cpu(folio) \
>> +	(((folio)->flags >> PG_dcache_cpu_shift) & PG_dcache_cpu_mask)
>>   
>> -static inline void set_dcache_dirty(struct page *page, int this_cpu)
>> +static inline void set_dcache_dirty(struct folio *folio, int this_cpu)
>>   {
>>   	unsigned long mask = this_cpu;
>>   	unsigned long non_cpu_bits;
>> @@ -238,11 +243,11 @@ static inline void set_dcache_dirty(struct page *page, int this_cpu)
>>   			     "bne,pn	%%xcc, 1b\n\t"
>>   			     " nop"
>>   			     : /* no outputs */
>> -			     : "r" (mask), "r" (non_cpu_bits), "r" (&page->flags)
>> +			     : "r" (mask), "r" (non_cpu_bits), "r" (&folio->flags)
>>   			     : "g1", "g7");
>>   }
>>   
>> -static inline void clear_dcache_dirty_cpu(struct page *page, unsigned long cpu)
>> +static inline void clear_dcache_dirty_cpu(struct folio *folio, unsigned long cpu)
>>   {
>>   	unsigned long mask = (1UL << PG_dcache_dirty);
>>   
>> @@ -260,7 +265,7 @@ static inline void clear_dcache_dirty_cpu(struct page *page, unsigned long cpu)
>>   			     " nop\n"
>>   			     "2:"
>>   			     : /* no outputs */
>> -			     : "r" (cpu), "r" (mask), "r" (&page->flags),
>> +			     : "r" (cpu), "r" (mask), "r" (&folio->flags),
>>   			       "i" (PG_dcache_cpu_mask),
>>   			       "i" (PG_dcache_cpu_shift)
>>   			     : "g1", "g7");
>> @@ -284,9 +289,10 @@ static void flush_dcache(unsigned long pfn)
>>   
>>   	page = pfn_to_page(pfn);
>>   	if (page) {
>> +		struct folio *folio = page_folio(page);
>>   		unsigned long pg_flags;
>>   
>> -		pg_flags = page->flags;
>> +		pg_flags = folio->flags;
>>   		if (pg_flags & (1UL << PG_dcache_dirty)) {
>>   			int cpu = ((pg_flags >> PG_dcache_cpu_shift) &
>>   				   PG_dcache_cpu_mask);
>> @@ -296,11 +302,11 @@ static void flush_dcache(unsigned long pfn)
>>   			 * in the SMP case.
>>   			 */
>>   			if (cpu == this_cpu)
>> -				flush_dcache_page_impl(page);
>> +				flush_dcache_folio_impl(folio);
>>   			else
>> -				smp_flush_dcache_page_impl(page, cpu);
>> +				smp_flush_dcache_folio_impl(folio, cpu);
>>   
>> -			clear_dcache_dirty_cpu(page, cpu);
>> +			clear_dcache_dirty_cpu(folio, cpu);
>>   
>>   			put_cpu();
>>   		}
>> @@ -388,12 +394,14 @@ bool __init arch_hugetlb_valid_size(unsigned long size)
>>   }
>>   #endif	/* CONFIG_HUGETLB_PAGE */
>>   
>> -void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
>> +void update_mmu_cache_range(struct vm_area_struct *vma, unsigned long address,
>> +		pte_t *ptep, unsigned int nr)
>>   {
>>   	struct mm_struct *mm;
>>   	unsigned long flags;
>>   	bool is_huge_tsb;
>>   	pte_t pte = *ptep;
>> +	unsigned int i;
>>   
>>   	if (tlb_type != hypervisor) {
>>   		unsigned long pfn = pte_pfn(pte);
>> @@ -440,15 +448,21 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *
>>   		}
>>   	}
>>   #endif
>> -	if (!is_huge_tsb)
>> -		__update_mmu_tsb_insert(mm, MM_TSB_BASE, PAGE_SHIFT,
>> -					address, pte_val(pte));
>> +	if (!is_huge_tsb) {
>> +		for (i = 0; i < nr; i++) {
>> +			__update_mmu_tsb_insert(mm, MM_TSB_BASE, PAGE_SHIFT,
>> +						address, pte_val(pte));
>> +			address += PAGE_SIZE;
>> +			pte_val(pte) += PAGE_SIZE;
>> +		}
>> +	}
>>   
>>   	spin_unlock_irqrestore(&mm->context.lock, flags);
>>   }
>>   
>> -void flush_dcache_page(struct page *page)
>> +void flush_dcache_folio(struct folio *folio)
>>   {
>> +	unsigned long pfn = folio_pfn(folio);
>>   	struct address_space *mapping;
>>   	int this_cpu;
>>   
>> @@ -459,35 +473,35 @@ void flush_dcache_page(struct page *page)
>>   	 * is merely the zero page.  The 'bigcore' testcase in GDB
>>   	 * causes this case to run millions of times.
>>   	 */
>> -	if (page == ZERO_PAGE(0))
>> +	if (is_zero_pfn(pfn))
>>   		return;
>>   
>>   	this_cpu = get_cpu();
>>   
>> -	mapping = page_mapping_file(page);
>> +	mapping = folio_flush_mapping(folio);
>>   	if (mapping && !mapping_mapped(mapping)) {
>> -		int dirty = test_bit(PG_dcache_dirty, &page->flags);
>> +		bool dirty = test_bit(PG_dcache_dirty, &folio->flags);
>>   		if (dirty) {
>> -			int dirty_cpu = dcache_dirty_cpu(page);
>> +			int dirty_cpu = dcache_dirty_cpu(folio);
>>   
>>   			if (dirty_cpu == this_cpu)
>>   				goto out;
>> -			smp_flush_dcache_page_impl(page, dirty_cpu);
>> +			smp_flush_dcache_folio_impl(folio, dirty_cpu);
>>   		}
>> -		set_dcache_dirty(page, this_cpu);
>> +		set_dcache_dirty(folio, this_cpu);
>>   	} else {
>>   		/* We could delay the flush for the !page_mapping
>>   		 * case too.  But that case is for exec env/arg
>>   		 * pages and those are %99 certainly going to get
>>   		 * faulted into the tlb (and thus flushed) anyways.
>>   		 */
>> -		flush_dcache_page_impl(page);
>> +		flush_dcache_folio_impl(folio);
>>   	}
>>   
>>   out:
>>   	put_cpu();
>>   }
>> -EXPORT_SYMBOL(flush_dcache_page);
>> +EXPORT_SYMBOL(flush_dcache_folio);
>>   
>>   void __kprobes flush_icache_range(unsigned long start, unsigned long end)
>>   {
>> @@ -2280,10 +2294,10 @@ void __init paging_init(void)
>>   	setup_page_offset();
>>   
>>   	/* These build time checkes make sure that the dcache_dirty_cpu()
>> -	 * page->flags usage will work.
>> +	 * folio->flags usage will work.
>>   	 *
>>   	 * When a page gets marked as dcache-dirty, we store the
>> -	 * cpu number starting at bit 32 in the page->flags.  Also,
>> +	 * cpu number starting at bit 32 in the folio->flags.  Also,
>>   	 * functions like clear_dcache_dirty_cpu use the cpu mask
>>   	 * in 13-bit signed-immediate instruction fields.
>>   	 */
>> diff --git a/arch/sparc/mm/tlb.c b/arch/sparc/mm/tlb.c
>> index 9a725547578e..3fa6a070912d 100644
>> --- a/arch/sparc/mm/tlb.c
>> +++ b/arch/sparc/mm/tlb.c
>> @@ -118,6 +118,7 @@ void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr,
>>   		unsigned long paddr, pfn = pte_pfn(orig);
>>   		struct address_space *mapping;
>>   		struct page *page;
>> +		struct folio *folio;
>>   
>>   		if (!pfn_valid(pfn))
>>   			goto no_cache_flush;
>> @@ -127,13 +128,13 @@ void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr,
>>   			goto no_cache_flush;
>>   
>>   		/* A real file page? */
>> -		mapping = page_mapping_file(page);
>> +		mapping = folio_flush_mapping(folio);
>>   		if (!mapping)
>>   			goto no_cache_flush;
>>   
>>   		paddr = (unsigned long) page_address(page);
>>   		if ((paddr ^ vaddr) & (1 << 13))
>> -			flush_dcache_page_all(mm, page);
>> +			flush_dcache_folio_all(mm, folio);
>>   	}
>>   
>>   no_cache_flush:
> 
> This change broke the kernel on sun4u SPARC systems. This has been observed on a Sun Netra 240.
> 
> During boot, the kernel crashes with:
> 
> [   25.855163] Unable to handle kernel NULL pointer dereference
> [   25.929588] tsk->{mm,active_mm}->context = 0000000000000001
> [   26.002772] tsk->{mm,active_mm}->pgd = fff00000001bc000
> [   26.071405]               \|/ ____ \|/
> [   26.071405]               "@'/ .. \`@"
> [   26.071405]               /_| \__/ |_\
> [   26.071405]                  \__U_/
> [   26.264705] modprobe(33): Oops [#1]
> [   26.310445] CPU: 0 PID: 33 Comm: modprobe Not tainted 6.5.0-rc4+ #16
> [   26.393937] TSTATE: 0000004411001601 TPC: 0000000000452a28 TNPC: 0000000000452a2c Y: 00000008    Not tainted
> [   26.523184] TPC: <tlb_batch_add+0x108/0x1a0>
> [   26.579221] g0: ace36c1f2cee4067 g1: 0000000000000028 g2: 00000000000a010c g3: 000c000000000000
> [   26.693607] g4: fff0000001947000 g5: 0000000000000000 g6: fff0000001948000 g7: fff000023fe33f00
> [   26.807978] o0: fff000000738fff8 o1: 000007feffffe000 o2: fff000000194b788 o3: 0000000000e3c038
> [   26.922356] o4: ffffffffffffffff o5: 0000000000e3c038 sp: fff000000194aee1 ret_pc: 000000000065d194
> [   27.041302] RPC: <__pte_offset_map_lock+0x14/0x60>
> [   27.104203] l0: fff000000194b860 l1: 0000000000000001 l2: 0000000000000000 l3: fff000000194b850
> [   27.218583] l4: 0000000000002000 l5: 00000000001010f8 l6: 0000000000000002 l7: 0000000000000040
> [   27.332959] i0: fff000000194e400 i1: 000007feffffe000 i2: 000c000004857588 i3: 80000002026d3fb2
> [   27.447334] i4: 0000000000000000 i5: 000000000000000d i6: fff000000194af91 i7: 0000000000659110
> [   27.561709] I7: <change_protection+0x910/0xe00>
> [   27.621178] Call Trace:
> [   27.653202] [<0000000000659110>] change_protection+0x910/0xe00
> [   27.729838] [<00000000006596f4>] mprotect_fixup+0xf4/0x2c0
> [   27.801892] [<00000000006c754c>] setup_arg_pages+0x12c/0x2c0
> [   27.876237] [<0000000000737d80>] load_elf_binary+0x360/0x1380
> [   27.951722] [<00000000006c8564>] bprm_execve+0x1e4/0x560
> [   28.021493] [<00000000006c8e8c>] kernel_execve+0x14c/0x200
> [   28.093548] [<000000000047f6e8>] call_usermodehelper_exec_async+0xa8/0x140
> [   28.183906] [<0000000000405fc8>] ret_from_fork+0x1c/0x2c
> [   28.253672] [<0000000000000000>] 0x0
> [   28.300568] Disabling lock debugging due to kernel taint
> [   28.370336] Caller[0000000000659110]: change_protection+0x910/0xe00
> [   28.452686] Caller[00000000006596f4]: mprotect_fixup+0xf4/0x2c0
> [   28.530461] Caller[00000000006c754c]: setup_arg_pages+0x12c/0x2c0
> [   28.610524] Caller[0000000000737d80]: load_elf_binary+0x360/0x1380
> [   28.691730] Caller[00000000006c8564]: bprm_execve+0x1e4/0x560
> [   28.767218] Caller[00000000006c8e8c]: kernel_execve+0x14c/0x200
> [   28.844993] Caller[000000000047f6e8]: call_usermodehelper_exec_async+0xa8/0x140
> [   28.941071] Caller[0000000000405fc8]: ret_from_fork+0x1c/0x2c
> [   29.016554] Caller[0000000000000000]: 0x0
> [   29.069167] Instruction DUMP:
> [   29.069169]  80886001
> [   29.108052]  126fffc8
> [   29.138932]  01000000
> [   29.169815] <c2582000>
> [   29.200697]  83307013
> [   29.231578]  80886001
> [   29.262458]  02680007
> [   29.293338]  01000000
> [   29.324223]  c2582000
> [   29.355102]
> 
> This crash is not observed on sun4v systems.
> 
> Any idea what could be the fix?

There was a follow-on fix that addressed a bug with this patch:

f4b4f3ec1a31 sparc64: add missing initialization of folio in tlb_batch_add()

Anthony

> 
> Adrian
> 


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v4 25/36] sparc64: Implement the new page table range API
  2025-08-03 19:08     ` Anthony Yznaga
@ 2025-08-04  5:12       ` John Paul Adrian Glaubitz
  2025-08-04  5:36         ` John Paul Adrian Glaubitz
  0 siblings, 1 reply; 11+ messages in thread
From: John Paul Adrian Glaubitz @ 2025-08-04  5:12 UTC (permalink / raw)
  To: Anthony Yznaga, Matthew Wilcox (Oracle), linux-arch
  Cc: linux-mm, linux-kernel, David S. Miller, sparclinux,
	Andreas Larsson, Rod Schnell, Sam James

Hi Anthony,

On Sun, 2025-08-03 at 12:08 -0700, Anthony Yznaga wrote:
> There was a follow-on fix that addressed a bug with this patch:
> 
> f4b4f3ec1a31 sparc64: add missing initialization of folio in tlb_batch_add()

Indeed I just tried v6.6 which has this patch and added your sun4u fix and it
seems to be stable. I was sure I saw problems even with v6.16 though.

Let me run more tests.

Adrian

-- 
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer
`. `'   Physicist
  `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v4 25/36] sparc64: Implement the new page table range API
  2025-08-04  5:12       ` John Paul Adrian Glaubitz
@ 2025-08-04  5:36         ` John Paul Adrian Glaubitz
  2025-08-04  6:58           ` John Paul Adrian Glaubitz
  0 siblings, 1 reply; 11+ messages in thread
From: John Paul Adrian Glaubitz @ 2025-08-04  5:36 UTC (permalink / raw)
  To: Anthony Yznaga, Matthew Wilcox (Oracle), linux-arch
  Cc: linux-mm, linux-kernel, David S. Miller, sparclinux,
	Andreas Larsson, Rod Schnell, Sam James

Hi Anthony,

On Mon, 2025-08-04 at 07:12 +0200, John Paul Adrian Glaubitz wrote:
> On Sun, 2025-08-03 at 12:08 -0700, Anthony Yznaga wrote:
> > There was a follow-on fix that addressed a bug with this patch:
> > 
> > f4b4f3ec1a31 sparc64: add missing initialization of folio in tlb_batch_add()
> 
> Indeed I just tried v6.6 which has this patch and added your sun4u fix and it
> seems to be stable. I was sure I saw problems even with v6.16 though.
> 
> Let me run more tests.

I'm seeing another crash on v6.16 on sun4u even with your patch applied:

[  456.443492] kernel BUG at fs/ext4/inode.c:1174!
[  456.503059]               \|/ ____ \|/
[  456.503059]               "@'/ .. \`@"
[  456.503059]               /_| \__/ |_\
[  456.503059]                  \__U_/
[  456.696513] apt-get(1217): Kernel bad sw trap 5 [#1]
[  456.761698] CPU: 0 UID: 0 PID: 1217 Comm: apt-get Not tainted 6.16.0+ #24 VOLUNTARY 
[  456.863502] TSTATE: 0000000011001601 TPC: 0000000010309250 TNPC: 0000000010309254 Y: 00000000    Not tainted
[  456.992850] TPC: <ext4_block_write_begin+0x450/0x540 [ext4]>
[  457.067500] g0: 0000000000000000 g1: 0000000000000001 g2: 0000000000000000 g3: 0000000000000000
[  457.181869] g4: fff00000141d5c80 g5: 0000000000000008 g6: fff000000be24000 g7: 0000000000000001
[  457.296245] o0: 00000000103944b0 o1: 0000000000000496 o2: ffffffffffffffbf o3: 0000000000101cca
[  457.410618] o4: 0000000000000000 o5: 0000000000000000 sp: fff000000be26fd1 ret_pc: 0000000010309248
[  457.529571] RPC: <ext4_block_write_begin+0x448/0x540 [ext4]>
[  457.604020] l0: fff000003def26e0 l1: 0000000000113cca l2: fff000003def2578 l3: 0000000000000002
[  457.718394] l4: 0000000000000000 l5: 0000000000080000 l6: 0000000000012000 l7: 0000000000000001
[  457.832770] i0: 0000000000000000 i1: 000c00000026b500 i2: 0000000000001000 i3: 0000000000082000
[  457.947146] i4: 00000000103034a0 i5: 0000000000000000 i6: fff000000be270c1 i7: 000000001030c8dc
[  458.061528] I7: <ext4_da_write_begin+0x1bc/0x340 [ext4]>
[  458.131389] Call Trace:
[  458.163408] [<000000001030c8dc>] ext4_da_write_begin+0x1bc/0x340 [ext4]
[  458.250447] [<0000000000674230>] generic_perform_write+0x90/0x240
[  458.330606] [<00000000102f50b4>] ext4_buffered_write_iter+0x54/0x120 [ext4]
[  458.422214] [<00000000102f5624>] ext4_file_write_iter+0x3e4/0x780 [ext4]
[  458.510388] [<0000000000749cc4>] vfs_write+0x2c4/0x3e0
[  458.577867] [<0000000000749f4c>] ksys_write+0x4c/0xe0
[  458.644203] [<0000000000749ff4>] sys_write+0x14/0x40
[  458.709397] [<0000000000406174>] linux_sparc_syscall+0x34/0x44
[  458.786048] Disabling lock debugging due to kernel taint
[  458.855904] Caller[000000001030c8dc]: ext4_da_write_begin+0x1bc/0x340 [ext4]
[  458.948653] Caller[0000000000674230]: generic_perform_write+0x90/0x240
[  459.034430] Caller[00000000102f50b4]: ext4_buffered_write_iter+0x54/0x120 [ext4]
[  459.131761] Caller[00000000102f5624]: ext4_file_write_iter+0x3e4/0x780 [ext4]
[  459.225648] Caller[0000000000749cc4]: vfs_write+0x2c4/0x3e0
[  459.298846] Caller[0000000000749f4c]: ksys_write+0x4c/0xe0
[  459.370900] Caller[0000000000749ff4]: sys_write+0x14/0x40
[  459.441810] Caller[0000000000406174]: linux_sparc_syscall+0x34/0x44
[  459.524168] Caller[0000000000000000]: 0x0
[  459.576772] Instruction DUMP:
[  459.576776]  11040e51 
[  459.615662]  7c04b816 
[  459.646541]  901220b0 
[  459.677418] <91d02005>
[  459.708302]  9735a000 
[  459.739181]  95352000 
[  459.770076]  d25fa7cf 
[  459.800945]  7fffe818 
[  459.831825]  90100019 
[  459.862706] 
[  459.941500] systemd[1]: Failed to open /dev/pts device, ignoring: Inappropriate ioctl for device
[  460.063831] systemd[1]: rsyslog.service: Main process exited, code=killed, status=6/ABRT
[  460.170962] systemd[1]: rsyslog.service: Failed with result 'signal'.
[  460.267153] systemd[1]: systemd-journald.service: Scheduled restart job, restart counter is at 1.
[  460.388605] systemd[1]: rsyslog.service: Scheduled restart job, restart counter is at 1.
[  460.517346] systemd[1]: Starting rsyslog.service - System Logging Service...
[  460.618299] systemd[1]: Starting systemd-journald.service - Journal Service...
[  460.895645] systemd-journald[1237]: Collecting audit messages is disabled.
[  461.048068] systemd[1]: Failed to open /dev/pts device, ignoring: Inappropriate ioctl for device
[  461.202783] systemd-journald[1237]: File /var/log/journal/9ac90e257b3e423284cfc21a00cbeeb8/system.journal corrupted or uncleanly shut down, renaming and replacing.
[  461.456867] systemd[1]: Started rsyslog.service - System Logging Service.
[  461.616651] systemd-journald[1237]: Time jumped backwards, rotating.
[  461.773305] systemd-journald[1237]: Failed to read journal file /var/log/journal/9ac90e257b3e423284cfc21a00cbeeb8/user-1002.journal for rotation, trying to move it out of the way: Device or
resource busy
[  462.065725] systemd[1]: Started systemd-journald.service - Journal Service.
[  462.159895] systemd-journald[1237]: Time jumped backwards, rotating.
[  519.719624] kernel BUG at fs/ext4/inode.c:1174!
[  519.779143]               \|/ ____ \|/
[  519.779143]               "@'/ .. \`@"
[  519.779143]               /_| \__/ |_\
[  519.779143]                  \__U_/
[  519.972586] apt(1249): Kernel bad sw trap 5 [#2]
[  520.033239] CPU: 0 UID: 0 PID: 1249 Comm: apt Tainted: G      D             6.16.0+ #24 VOLUNTARY 
[  520.151048] Tainted: [D]=DIE
[  520.188797] TSTATE: 0000000011001603 TPC: 0000000010309250 TNPC: 0000000010309254 Y: 00000000    Tainted: G      D            
[  520.338725] TPC: <ext4_block_write_begin+0x450/0x540 [ext4]>
[  520.413282] g0: 0000000000000000 g1: 0000000000000001 g2: 0000000000000000 g3: 0000000000000000
[  520.527655] g4: fff00000141d40c0 g5: 000000000000000b g6: fff000000a818000 g7: 0000000000000001
[  520.642031] o0: 00000000103944b0 o1: 0000000000000496 o2: fffffffffffffcc0 o3: 0000000000101cca
[  520.756408] o4: 0000000000000004 o5: 0000000000000000 sp: fff000000a81afd1 ret_pc: 0000000010309248
[  520.875350] RPC: <ext4_block_write_begin+0x448/0x540 [ext4]>
[  520.949799] l0: fff000023439af00 l1: 0000000000113cca l2: fff000023439ad98 l3: 0000000000000002
[  521.064174] l4: 0000000000000000 l5: 0000000000080000 l6: 0000000000012000 l7: 0000000000000001
[  521.178547] i0: 0000000000000000 i1: 000c000000164a00 i2: 0000000000001fc0 i3: 0000000000680000
[  521.292923] i4: 00000000103034a0 i5: 0000000000000000 i6: fff000000a81b0c1 i7: 000000001030c8dc
[  521.407297] I7: <ext4_da_write_begin+0x1bc/0x340 [ext4]>
[  521.477195] Call Trace:
[  521.509295] [<000000001030c8dc>] ext4_da_write_begin+0x1bc/0x340 [ext4]
[  521.596330] [<0000000000674230>] generic_perform_write+0x90/0x240
[  521.676495] [<00000000102f50b4>] ext4_buffered_write_iter+0x54/0x120 [ext4]
[  521.768196] [<00000000102f5624>] ext4_file_write_iter+0x3e4/0x780 [ext4]
[  521.856381] [<0000000000749cc4>] vfs_write+0x2c4/0x3e0
[  521.923957] [<0000000000749f4c>] ksys_write+0x4c/0xe0
[  521.990294] [<0000000000749ff4>] sys_write+0x14/0x40
[  522.055486] [<0000000000406174>] linux_sparc_syscall+0x34/0x44
[  522.132122] Caller[000000001030c8dc]: ext4_da_write_begin+0x1bc/0x340 [ext4]
[  522.224873] Caller[0000000000674230]: generic_perform_write+0x90/0x240
[  522.310649] Caller[00000000102f50b4]: ext4_buffered_write_iter+0x54/0x120 [ext4]
[  522.407974] Caller[00000000102f5624]: ext4_file_write_iter+0x3e4/0x780 [ext4]
[  522.501864] Caller[0000000000749cc4]: vfs_write+0x2c4/0x3e0
[  522.575062] Caller[0000000000749f4c]: ksys_write+0x4c/0xe0
[  522.647118] Caller[0000000000749ff4]: sys_write+0x14/0x40
[  522.718031] Caller[0000000000406174]: linux_sparc_syscall+0x34/0x44
[  522.800380] Caller[0000000000000000]: 0x0
[  522.852991] Instruction DUMP:
[  522.852994]  11040e51 
[  522.891878]  7c04b816 
[  522.922760]  901220b0 
[  522.953638] <91d02005>
[  522.984521]  9735a000 
[  523.015401]  95352000 
[  523.046284]  d25fa7cf 
[  523.077163]  7fffe818 
[  523.108109]  90100019 
[  523.139044]

I'll try to bisect this one later this week.

Adrian

-- 
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer
`. `'   Physicist
  `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v4 25/36] sparc64: Implement the new page table range API
  2025-08-04  5:36         ` John Paul Adrian Glaubitz
@ 2025-08-04  6:58           ` John Paul Adrian Glaubitz
  2025-08-04  7:48             ` John Paul Adrian Glaubitz
  2025-08-04  9:38             ` John Paul Adrian Glaubitz
  0 siblings, 2 replies; 11+ messages in thread
From: John Paul Adrian Glaubitz @ 2025-08-04  6:58 UTC (permalink / raw)
  To: Anthony Yznaga, Matthew Wilcox (Oracle), linux-arch
  Cc: linux-mm, linux-kernel, David S. Miller, sparclinux,
	Andreas Larsson, Rod Schnell, Sam James

Hi,

On Mon, 2025-08-04 at 07:36 +0200, John Paul Adrian Glaubitz wrote:
> On Mon, 2025-08-04 at 07:12 +0200, John Paul Adrian Glaubitz wrote:
> > On Sun, 2025-08-03 at 12:08 -0700, Anthony Yznaga wrote:
> > > There was a follow-on fix that addressed a bug with this patch:
> > > 
> > > f4b4f3ec1a31 sparc64: add missing initialization of folio in tlb_batch_add()
> > 
> > Indeed I just tried v6.6 which has this patch and added your sun4u fix and it
> > seems to be stable. I was sure I saw problems even with v6.16 though.
> > 
> > Let me run more tests.
> 
> I'm seeing another crash on v6.16 on sun4u even with your patch applied:
> 
> [  456.443492] kernel BUG at fs/ext4/inode.c:1174!
> [  456.503059]               \|/ ____ \|/
> [  456.503059]               "@'/ .. \`@"
> [  456.503059]               /_| \__/ |_\
> [  456.503059]                  \__U_/
> [  456.696513] apt-get(1217): Kernel bad sw trap 5 [#1]
> [  456.761698] CPU: 0 UID: 0 PID: 1217 Comm: apt-get Not tainted 6.16.0+ #24 VOLUNTARY 
> [  456.863502] TSTATE: 0000000011001601 TPC: 0000000010309250 TNPC: 0000000010309254 Y: 00000000    Not tainted
> [  456.992850] TPC: <ext4_block_write_begin+0x450/0x540 [ext4]>
> [  457.067500] g0: 0000000000000000 g1: 0000000000000001 g2: 0000000000000000 g3: 0000000000000000
> [  457.181869] g4: fff00000141d5c80 g5: 0000000000000008 g6: fff000000be24000 g7: 0000000000000001
> [  457.296245] o0: 00000000103944b0 o1: 0000000000000496 o2: ffffffffffffffbf o3: 0000000000101cca
> [  457.410618] o4: 0000000000000000 o5: 0000000000000000 sp: fff000000be26fd1 ret_pc: 0000000010309248
> [  457.529571] RPC: <ext4_block_write_begin+0x448/0x540 [ext4]>
> [  457.604020] l0: fff000003def26e0 l1: 0000000000113cca l2: fff000003def2578 l3: 0000000000000002
> [  457.718394] l4: 0000000000000000 l5: 0000000000080000 l6: 0000000000012000 l7: 0000000000000001
> [  457.832770] i0: 0000000000000000 i1: 000c00000026b500 i2: 0000000000001000 i3: 0000000000082000
> [  457.947146] i4: 00000000103034a0 i5: 0000000000000000 i6: fff000000be270c1 i7: 000000001030c8dc
> [  458.061528] I7: <ext4_da_write_begin+0x1bc/0x340 [ext4]>
> [  458.131389] Call Trace:
> [  458.163408] [<000000001030c8dc>] ext4_da_write_begin+0x1bc/0x340 [ext4]
> [  458.250447] [<0000000000674230>] generic_perform_write+0x90/0x240
> [  458.330606] [<00000000102f50b4>] ext4_buffered_write_iter+0x54/0x120 [ext4]
> [  458.422214] [<00000000102f5624>] ext4_file_write_iter+0x3e4/0x780 [ext4]
> [  458.510388] [<0000000000749cc4>] vfs_write+0x2c4/0x3e0
> [  458.577867] [<0000000000749f4c>] ksys_write+0x4c/0xe0
> [  458.644203] [<0000000000749ff4>] sys_write+0x14/0x40
> [  458.709397] [<0000000000406174>] linux_sparc_syscall+0x34/0x44
> [  458.786048] Disabling lock debugging due to kernel taint
> [  458.855904] Caller[000000001030c8dc]: ext4_da_write_begin+0x1bc/0x340 [ext4]
> [  458.948653] Caller[0000000000674230]: generic_perform_write+0x90/0x240
> [  459.034430] Caller[00000000102f50b4]: ext4_buffered_write_iter+0x54/0x120 [ext4]
> [  459.131761] Caller[00000000102f5624]: ext4_file_write_iter+0x3e4/0x780 [ext4]
> [  459.225648] Caller[0000000000749cc4]: vfs_write+0x2c4/0x3e0
> [  459.298846] Caller[0000000000749f4c]: ksys_write+0x4c/0xe0
> [  459.370900] Caller[0000000000749ff4]: sys_write+0x14/0x40
> [  459.441810] Caller[0000000000406174]: linux_sparc_syscall+0x34/0x44
> [  459.524168] Caller[0000000000000000]: 0x0
> [  459.576772] Instruction DUMP:
> [  459.576776]  11040e51 
> [  459.615662]  7c04b816 
> [  459.646541]  901220b0 
> [  459.677418] <91d02005>
> [  459.708302]  9735a000 
> [  459.739181]  95352000 
> [  459.770076]  d25fa7cf 
> [  459.800945]  7fffe818 
> [  459.831825]  90100019 
> [  459.862706] 
> [  459.941500] systemd[1]: Failed to open /dev/pts device, ignoring: Inappropriate ioctl for device
> [  460.063831] systemd[1]: rsyslog.service: Main process exited, code=killed, status=6/ABRT
> [  460.170962] systemd[1]: rsyslog.service: Failed with result 'signal'.
> [  460.267153] systemd[1]: systemd-journald.service: Scheduled restart job, restart counter is at 1.
> [  460.388605] systemd[1]: rsyslog.service: Scheduled restart job, restart counter is at 1.
> [  460.517346] systemd[1]: Starting rsyslog.service - System Logging Service...
> [  460.618299] systemd[1]: Starting systemd-journald.service - Journal Service...
> [  460.895645] systemd-journald[1237]: Collecting audit messages is disabled.
> [  461.048068] systemd[1]: Failed to open /dev/pts device, ignoring: Inappropriate ioctl for device
> [  461.202783] systemd-journald[1237]: File /var/log/journal/9ac90e257b3e423284cfc21a00cbeeb8/system.journal corrupted or uncleanly shut down, renaming and replacing.
> [  461.456867] systemd[1]: Started rsyslog.service - System Logging Service.
> [  461.616651] systemd-journald[1237]: Time jumped backwards, rotating.
> [  461.773305] systemd-journald[1237]: Failed to read journal file /var/log/journal/9ac90e257b3e423284cfc21a00cbeeb8/user-1002.journal for rotation, trying to move it out of the way: Device or
> resource busy
> [  462.065725] systemd[1]: Started systemd-journald.service - Journal Service.
> [  462.159895] systemd-journald[1237]: Time jumped backwards, rotating.
> [  519.719624] kernel BUG at fs/ext4/inode.c:1174!
> [  519.779143]               \|/ ____ \|/
> [  519.779143]               "@'/ .. \`@"
> [  519.779143]               /_| \__/ |_\
> [  519.779143]                  \__U_/
> [  519.972586] apt(1249): Kernel bad sw trap 5 [#2]
> [  520.033239] CPU: 0 UID: 0 PID: 1249 Comm: apt Tainted: G      D             6.16.0+ #24 VOLUNTARY 
> [  520.151048] Tainted: [D]=DIE
> [  520.188797] TSTATE: 0000000011001603 TPC: 0000000010309250 TNPC: 0000000010309254 Y: 00000000    Tainted: G      D            
> [  520.338725] TPC: <ext4_block_write_begin+0x450/0x540 [ext4]>
> [  520.413282] g0: 0000000000000000 g1: 0000000000000001 g2: 0000000000000000 g3: 0000000000000000
> [  520.527655] g4: fff00000141d40c0 g5: 000000000000000b g6: fff000000a818000 g7: 0000000000000001
> [  520.642031] o0: 00000000103944b0 o1: 0000000000000496 o2: fffffffffffffcc0 o3: 0000000000101cca
> [  520.756408] o4: 0000000000000004 o5: 0000000000000000 sp: fff000000a81afd1 ret_pc: 0000000010309248
> [  520.875350] RPC: <ext4_block_write_begin+0x448/0x540 [ext4]>
> [  520.949799] l0: fff000023439af00 l1: 0000000000113cca l2: fff000023439ad98 l3: 0000000000000002
> [  521.064174] l4: 0000000000000000 l5: 0000000000080000 l6: 0000000000012000 l7: 0000000000000001
> [  521.178547] i0: 0000000000000000 i1: 000c000000164a00 i2: 0000000000001fc0 i3: 0000000000680000
> [  521.292923] i4: 00000000103034a0 i5: 0000000000000000 i6: fff000000a81b0c1 i7: 000000001030c8dc
> [  521.407297] I7: <ext4_da_write_begin+0x1bc/0x340 [ext4]>
> [  521.477195] Call Trace:
> [  521.509295] [<000000001030c8dc>] ext4_da_write_begin+0x1bc/0x340 [ext4]
> [  521.596330] [<0000000000674230>] generic_perform_write+0x90/0x240
> [  521.676495] [<00000000102f50b4>] ext4_buffered_write_iter+0x54/0x120 [ext4]
> [  521.768196] [<00000000102f5624>] ext4_file_write_iter+0x3e4/0x780 [ext4]
> [  521.856381] [<0000000000749cc4>] vfs_write+0x2c4/0x3e0
> [  521.923957] [<0000000000749f4c>] ksys_write+0x4c/0xe0
> [  521.990294] [<0000000000749ff4>] sys_write+0x14/0x40
> [  522.055486] [<0000000000406174>] linux_sparc_syscall+0x34/0x44
> [  522.132122] Caller[000000001030c8dc]: ext4_da_write_begin+0x1bc/0x340 [ext4]
> [  522.224873] Caller[0000000000674230]: generic_perform_write+0x90/0x240
> [  522.310649] Caller[00000000102f50b4]: ext4_buffered_write_iter+0x54/0x120 [ext4]
> [  522.407974] Caller[00000000102f5624]: ext4_file_write_iter+0x3e4/0x780 [ext4]
> [  522.501864] Caller[0000000000749cc4]: vfs_write+0x2c4/0x3e0
> [  522.575062] Caller[0000000000749f4c]: ksys_write+0x4c/0xe0
> [  522.647118] Caller[0000000000749ff4]: sys_write+0x14/0x40
> [  522.718031] Caller[0000000000406174]: linux_sparc_syscall+0x34/0x44
> [  522.800380] Caller[0000000000000000]: 0x0
> [  522.852991] Instruction DUMP:
> [  522.852994]  11040e51 
> [  522.891878]  7c04b816 
> [  522.922760]  901220b0 
> [  522.953638] <91d02005>
> [  522.984521]  9735a000 
> [  523.015401]  95352000 
> [  523.046284]  d25fa7cf 
> [  523.077163]  7fffe818 
> [  523.108109]  90100019 
> [  523.139044]
> 
> I'll try to bisect this one later this week.

OK, so v6.8 is fine while v6.9 crashes:

[   39.788224] Unable to handle kernel NULL pointer dereference
[   39.862657] tsk->{mm,active_mm}->context = 000000000000004b
[   39.935941] tsk->{mm,active_mm}->pgd = fff000000aa98000
[   40.004566]               \|/ ____ \|/
[   40.004566]               "@'/ .. \`@"
[   40.004566]               /_| \__/ |_\
[   40.004566]                  \__U_/
[   40.197871] (udev-worker)(88): Oops [#1]
[   40.249329] CPU: 0 PID: 88 Comm: (udev-worker) Tainted: P           O       6.9.0+ #28
[   40.353415] TSTATE: 0000004411001605 TPC: 0000000000df092c TNPC: 0000000000df0930 Y: 00000000    Tainted: P           O      
[   40.502105] TPC: <strlen+0x60/0xd4>
[   40.547844] g0: fff000000a3171a1 g1: 0000000000000000 g2: 0000000000000000 g3: 0000000000000001
[   40.662224] g4: fff000000aa4dac0 g5: 0000000010000233 g6: fff000000a314000 g7: 0000000000000000
[   40.776599] o0: 0000000000000010 o1: 0000000000000010 o2: 0000000001010101 o3: 0000000080808080
[   40.890974] o4: 0000000001010000 o5: 0000000000000000 sp: fff000000a317201 ret_pc: 00000000004d4b08
[   41.009924] RPC: <module_patient_check_exists.constprop.0+0x48/0x1e0>
[   41.094557] l0: fff0000100032f40 l1: 0000000000000000 l2: 0000000000000000 l3: 0000000000000000
[   41.208936] l4: 0000000000000000 l5: 0000000000000000 l6: 0000000000000000 l7: 0000000000000000
[   41.323311] i0: 00000001000256d8 i1: 0000000001143000 i2: 0000000001143300 i3: 000000000000000b
[   41.437686] i4: 0000000000000010 i5: fffffffffffffff8 i6: fff000000a3172e1 i7: 00000000004d63f0
[   41.552062] I7: <load_module+0x550/0x1f00>
[   41.605811] Call Trace:
[   41.637838] [<00000000004d63f0>] load_module+0x550/0x1f00
[   41.708752] [<00000000004d7fac>] init_module_from_file+0x6c/0xa0
[   41.787670] [<00000000004d81c8>] sys_finit_module+0x188/0x280
[   41.863158] [<0000000000406174>] linux_sparc_syscall+0x34/0x44
[   41.939790] Caller[00000000004d63f0]: load_module+0x550/0x1f00
[   42.016423] Caller[00000000004d7fac]: init_module_from_file+0x6c/0xa0
[   42.101059] Caller[00000000004d81c8]: sys_finit_module+0x188/0x280
[   42.182266] Caller[0000000000406174]: linux_sparc_syscall+0x34/0x44
[   42.264614] Caller[fff000010480e2fc]: 0xfff000010480e2fc
[   42.334384] Instruction DUMP:
[   42.334387]  96132080 
[   42.373269]  19004040 
[   42.404151]  94132101 
[   42.435030] <da020000>
[   42.465914]  9823400a 
[   42.496793]  808b000b 
[   42.527674]  024ffffd 
[   42.558556]  90022004 
[   42.589437]  8f336018 
[   42.620318]

So, the regression was introduced with v6.9. Will bisect this later this week.

Adrian

-- 
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer
`. `'   Physicist
  `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v4 25/36] sparc64: Implement the new page table range API
  2025-08-04  6:58           ` John Paul Adrian Glaubitz
@ 2025-08-04  7:48             ` John Paul Adrian Glaubitz
  2025-08-04  9:38             ` John Paul Adrian Glaubitz
  1 sibling, 0 replies; 11+ messages in thread
From: John Paul Adrian Glaubitz @ 2025-08-04  7:48 UTC (permalink / raw)
  To: Anthony Yznaga, Matthew Wilcox (Oracle), linux-arch
  Cc: linux-mm, linux-kernel, David S. Miller, sparclinux,
	Andreas Larsson, Rod Schnell, Sam James

Hi,

On Mon, 2025-08-04 at 08:58 +0200, John Paul Adrian Glaubitz wrote:
> On Mon, 2025-08-04 at 07:36 +0200, John Paul Adrian Glaubitz wrote:
> > On Mon, 2025-08-04 at 07:12 +0200, John Paul Adrian Glaubitz wrote:
> > > On Sun, 2025-08-03 at 12:08 -0700, Anthony Yznaga wrote:
> > > > There was a follow-on fix that addressed a bug with this patch:
> > > > 
> > > > f4b4f3ec1a31 sparc64: add missing initialization of folio in tlb_batch_add()
> > > 
> > > Indeed I just tried v6.6 which has this patch and added your sun4u fix and it
> > > seems to be stable. I was sure I saw problems even with v6.16 though.
> > > 
> > > Let me run more tests.
> > 
> > I'm seeing another crash on v6.16 on sun4u even with your patch applied:
> > 
> > [  456.443492] kernel BUG at fs/ext4/inode.c:1174!
> > [  456.503059]               \|/ ____ \|/
> > [  456.503059]               "@'/ .. \`@"
> > [  456.503059]               /_| \__/ |_\
> > [  456.503059]                  \__U_/
> > [  456.696513] apt-get(1217): Kernel bad sw trap 5 [#1]
> > [  456.761698] CPU: 0 UID: 0 PID: 1217 Comm: apt-get Not tainted 6.16.0+ #24 VOLUNTARY 
> > [  456.863502] TSTATE: 0000000011001601 TPC: 0000000010309250 TNPC: 0000000010309254 Y: 00000000    Not tainted
> > [  456.992850] TPC: <ext4_block_write_begin+0x450/0x540 [ext4]>
> > [  457.067500] g0: 0000000000000000 g1: 0000000000000001 g2: 0000000000000000 g3: 0000000000000000
> > [  457.181869] g4: fff00000141d5c80 g5: 0000000000000008 g6: fff000000be24000 g7: 0000000000000001
> > [  457.296245] o0: 00000000103944b0 o1: 0000000000000496 o2: ffffffffffffffbf o3: 0000000000101cca
> > [  457.410618] o4: 0000000000000000 o5: 0000000000000000 sp: fff000000be26fd1 ret_pc: 0000000010309248
> > [  457.529571] RPC: <ext4_block_write_begin+0x448/0x540 [ext4]>
> > [  457.604020] l0: fff000003def26e0 l1: 0000000000113cca l2: fff000003def2578 l3: 0000000000000002
> > [  457.718394] l4: 0000000000000000 l5: 0000000000080000 l6: 0000000000012000 l7: 0000000000000001
> > [  457.832770] i0: 0000000000000000 i1: 000c00000026b500 i2: 0000000000001000 i3: 0000000000082000
> > [  457.947146] i4: 00000000103034a0 i5: 0000000000000000 i6: fff000000be270c1 i7: 000000001030c8dc
> > [  458.061528] I7: <ext4_da_write_begin+0x1bc/0x340 [ext4]>
> > [  458.131389] Call Trace:
> > [  458.163408] [<000000001030c8dc>] ext4_da_write_begin+0x1bc/0x340 [ext4]
> > [  458.250447] [<0000000000674230>] generic_perform_write+0x90/0x240
> > [  458.330606] [<00000000102f50b4>] ext4_buffered_write_iter+0x54/0x120 [ext4]
> > [  458.422214] [<00000000102f5624>] ext4_file_write_iter+0x3e4/0x780 [ext4]
> > [  458.510388] [<0000000000749cc4>] vfs_write+0x2c4/0x3e0
> > [  458.577867] [<0000000000749f4c>] ksys_write+0x4c/0xe0
> > [  458.644203] [<0000000000749ff4>] sys_write+0x14/0x40
> > [  458.709397] [<0000000000406174>] linux_sparc_syscall+0x34/0x44
> > [  458.786048] Disabling lock debugging due to kernel taint
> > [  458.855904] Caller[000000001030c8dc]: ext4_da_write_begin+0x1bc/0x340 [ext4]
> > [  458.948653] Caller[0000000000674230]: generic_perform_write+0x90/0x240
> > [  459.034430] Caller[00000000102f50b4]: ext4_buffered_write_iter+0x54/0x120 [ext4]
> > [  459.131761] Caller[00000000102f5624]: ext4_file_write_iter+0x3e4/0x780 [ext4]
> > [  459.225648] Caller[0000000000749cc4]: vfs_write+0x2c4/0x3e0
> > [  459.298846] Caller[0000000000749f4c]: ksys_write+0x4c/0xe0
> > [  459.370900] Caller[0000000000749ff4]: sys_write+0x14/0x40
> > [  459.441810] Caller[0000000000406174]: linux_sparc_syscall+0x34/0x44
> > [  459.524168] Caller[0000000000000000]: 0x0
> > [  459.576772] Instruction DUMP:
> > [  459.576776]  11040e51 
> > [  459.615662]  7c04b816 
> > [  459.646541]  901220b0 
> > [  459.677418] <91d02005>
> > [  459.708302]  9735a000 
> > [  459.739181]  95352000 
> > [  459.770076]  d25fa7cf 
> > [  459.800945]  7fffe818 
> > [  459.831825]  90100019 
> > [  459.862706] 
> > [  459.941500] systemd[1]: Failed to open /dev/pts device, ignoring: Inappropriate ioctl for device
> > [  460.063831] systemd[1]: rsyslog.service: Main process exited, code=killed, status=6/ABRT
> > [  460.170962] systemd[1]: rsyslog.service: Failed with result 'signal'.
> > [  460.267153] systemd[1]: systemd-journald.service: Scheduled restart job, restart counter is at 1.
> > [  460.388605] systemd[1]: rsyslog.service: Scheduled restart job, restart counter is at 1.
> > [  460.517346] systemd[1]: Starting rsyslog.service - System Logging Service...
> > [  460.618299] systemd[1]: Starting systemd-journald.service - Journal Service...
> > [  460.895645] systemd-journald[1237]: Collecting audit messages is disabled.
> > [  461.048068] systemd[1]: Failed to open /dev/pts device, ignoring: Inappropriate ioctl for device
> > [  461.202783] systemd-journald[1237]: File /var/log/journal/9ac90e257b3e423284cfc21a00cbeeb8/system.journal corrupted or uncleanly shut down, renaming and replacing.
> > [  461.456867] systemd[1]: Started rsyslog.service - System Logging Service.
> > [  461.616651] systemd-journald[1237]: Time jumped backwards, rotating.
> > [  461.773305] systemd-journald[1237]: Failed to read journal file /var/log/journal/9ac90e257b3e423284cfc21a00cbeeb8/user-1002.journal for rotation, trying to move it out of the way: Device or
> > resource busy
> > [  462.065725] systemd[1]: Started systemd-journald.service - Journal Service.
> > [  462.159895] systemd-journald[1237]: Time jumped backwards, rotating.
> > [  519.719624] kernel BUG at fs/ext4/inode.c:1174!
> > [  519.779143]               \|/ ____ \|/
> > [  519.779143]               "@'/ .. \`@"
> > [  519.779143]               /_| \__/ |_\
> > [  519.779143]                  \__U_/
> > [  519.972586] apt(1249): Kernel bad sw trap 5 [#2]
> > [  520.033239] CPU: 0 UID: 0 PID: 1249 Comm: apt Tainted: G      D             6.16.0+ #24 VOLUNTARY 
> > [  520.151048] Tainted: [D]=DIE
> > [  520.188797] TSTATE: 0000000011001603 TPC: 0000000010309250 TNPC: 0000000010309254 Y: 00000000    Tainted: G      D            
> > [  520.338725] TPC: <ext4_block_write_begin+0x450/0x540 [ext4]>
> > [  520.413282] g0: 0000000000000000 g1: 0000000000000001 g2: 0000000000000000 g3: 0000000000000000
> > [  520.527655] g4: fff00000141d40c0 g5: 000000000000000b g6: fff000000a818000 g7: 0000000000000001
> > [  520.642031] o0: 00000000103944b0 o1: 0000000000000496 o2: fffffffffffffcc0 o3: 0000000000101cca
> > [  520.756408] o4: 0000000000000004 o5: 0000000000000000 sp: fff000000a81afd1 ret_pc: 0000000010309248
> > [  520.875350] RPC: <ext4_block_write_begin+0x448/0x540 [ext4]>
> > [  520.949799] l0: fff000023439af00 l1: 0000000000113cca l2: fff000023439ad98 l3: 0000000000000002
> > [  521.064174] l4: 0000000000000000 l5: 0000000000080000 l6: 0000000000012000 l7: 0000000000000001
> > [  521.178547] i0: 0000000000000000 i1: 000c000000164a00 i2: 0000000000001fc0 i3: 0000000000680000
> > [  521.292923] i4: 00000000103034a0 i5: 0000000000000000 i6: fff000000a81b0c1 i7: 000000001030c8dc
> > [  521.407297] I7: <ext4_da_write_begin+0x1bc/0x340 [ext4]>
> > [  521.477195] Call Trace:
> > [  521.509295] [<000000001030c8dc>] ext4_da_write_begin+0x1bc/0x340 [ext4]
> > [  521.596330] [<0000000000674230>] generic_perform_write+0x90/0x240
> > [  521.676495] [<00000000102f50b4>] ext4_buffered_write_iter+0x54/0x120 [ext4]
> > [  521.768196] [<00000000102f5624>] ext4_file_write_iter+0x3e4/0x780 [ext4]
> > [  521.856381] [<0000000000749cc4>] vfs_write+0x2c4/0x3e0
> > [  521.923957] [<0000000000749f4c>] ksys_write+0x4c/0xe0
> > [  521.990294] [<0000000000749ff4>] sys_write+0x14/0x40
> > [  522.055486] [<0000000000406174>] linux_sparc_syscall+0x34/0x44
> > [  522.132122] Caller[000000001030c8dc]: ext4_da_write_begin+0x1bc/0x340 [ext4]
> > [  522.224873] Caller[0000000000674230]: generic_perform_write+0x90/0x240
> > [  522.310649] Caller[00000000102f50b4]: ext4_buffered_write_iter+0x54/0x120 [ext4]
> > [  522.407974] Caller[00000000102f5624]: ext4_file_write_iter+0x3e4/0x780 [ext4]
> > [  522.501864] Caller[0000000000749cc4]: vfs_write+0x2c4/0x3e0
> > [  522.575062] Caller[0000000000749f4c]: ksys_write+0x4c/0xe0
> > [  522.647118] Caller[0000000000749ff4]: sys_write+0x14/0x40
> > [  522.718031] Caller[0000000000406174]: linux_sparc_syscall+0x34/0x44
> > [  522.800380] Caller[0000000000000000]: 0x0
> > [  522.852991] Instruction DUMP:
> > [  522.852994]  11040e51 
> > [  522.891878]  7c04b816 
> > [  522.922760]  901220b0 
> > [  522.953638] <91d02005>
> > [  522.984521]  9735a000 
> > [  523.015401]  95352000 
> > [  523.046284]  d25fa7cf 
> > [  523.077163]  7fffe818 
> > [  523.108109]  90100019 
> > [  523.139044]
> > 
> > I'll try to bisect this one later this week.
> 
> OK, so v6.8 is fine while v6.9 crashes:
> 
> [   39.788224] Unable to handle kernel NULL pointer dereference
> [   39.862657] tsk->{mm,active_mm}->context = 000000000000004b
> [   39.935941] tsk->{mm,active_mm}->pgd = fff000000aa98000
> [   40.004566]               \|/ ____ \|/
> [   40.004566]               "@'/ .. \`@"
> [   40.004566]               /_| \__/ |_\
> [   40.004566]                  \__U_/
> [   40.197871] (udev-worker)(88): Oops [#1]
> [   40.249329] CPU: 0 PID: 88 Comm: (udev-worker) Tainted: P           O       6.9.0+ #28
> [   40.353415] TSTATE: 0000004411001605 TPC: 0000000000df092c TNPC: 0000000000df0930 Y: 00000000    Tainted: P           O      
> [   40.502105] TPC: <strlen+0x60/0xd4>
> [   40.547844] g0: fff000000a3171a1 g1: 0000000000000000 g2: 0000000000000000 g3: 0000000000000001
> [   40.662224] g4: fff000000aa4dac0 g5: 0000000010000233 g6: fff000000a314000 g7: 0000000000000000
> [   40.776599] o0: 0000000000000010 o1: 0000000000000010 o2: 0000000001010101 o3: 0000000080808080
> [   40.890974] o4: 0000000001010000 o5: 0000000000000000 sp: fff000000a317201 ret_pc: 00000000004d4b08
> [   41.009924] RPC: <module_patient_check_exists.constprop.0+0x48/0x1e0>
> [   41.094557] l0: fff0000100032f40 l1: 0000000000000000 l2: 0000000000000000 l3: 0000000000000000
> [   41.208936] l4: 0000000000000000 l5: 0000000000000000 l6: 0000000000000000 l7: 0000000000000000
> [   41.323311] i0: 00000001000256d8 i1: 0000000001143000 i2: 0000000001143300 i3: 000000000000000b
> [   41.437686] i4: 0000000000000010 i5: fffffffffffffff8 i6: fff000000a3172e1 i7: 00000000004d63f0
> [   41.552062] I7: <load_module+0x550/0x1f00>
> [   41.605811] Call Trace:
> [   41.637838] [<00000000004d63f0>] load_module+0x550/0x1f00
> [   41.708752] [<00000000004d7fac>] init_module_from_file+0x6c/0xa0
> [   41.787670] [<00000000004d81c8>] sys_finit_module+0x188/0x280
> [   41.863158] [<0000000000406174>] linux_sparc_syscall+0x34/0x44
> [   41.939790] Caller[00000000004d63f0]: load_module+0x550/0x1f00
> [   42.016423] Caller[00000000004d7fac]: init_module_from_file+0x6c/0xa0
> [   42.101059] Caller[00000000004d81c8]: sys_finit_module+0x188/0x280
> [   42.182266] Caller[0000000000406174]: linux_sparc_syscall+0x34/0x44
> [   42.264614] Caller[fff000010480e2fc]: 0xfff000010480e2fc
> [   42.334384] Instruction DUMP:
> [   42.334387]  96132080 
> [   42.373269]  19004040 
> [   42.404151]  94132101 
> [   42.435030] <da020000>
> [   42.465914]  9823400a 
> [   42.496793]  808b000b 
> [   42.527674]  024ffffd 
> [   42.558556]  90022004 
> [   42.589437]  8f336018 
> [   42.620318]
> 
> So, the regression was introduced with v6.9. Will bisect this later this week.

Hmm, I just ran into another crash on v6.8. The machine didn't crash though:

[  489.263666] Unable to handle kernel paging request at virtual address 000c000002400000
[  489.367912] tsk->{mm,active_mm}->context = 00000000000013b2
[  489.441150] tsk->{mm,active_mm}->pgd = fff000000af04000
[  489.509872]               \|/ ____ \|/
                             "@'/ .. \`@"
                             /_| \__/ |_\
                                \__U_/
[  489.703156] sshd-session(3671): Oops [#1]
[  489.755758] CPU: 0 PID: 3671 Comm: sshd-session Not tainted 6.8.0+ #27
[  489.841544] TSTATE: 0000000811001600 TPC: 000000000065d620 TNPC: 000000000065d624 Y: 00000000    Not tainted
[  489.970796] TPC: <unmap_page_range+0x620/0xc60>
[  490.030362] g0: fff000000a939360 g1: 0000000000008800 g2: ffffffffffffffff g3: ffffffffffffffff
[  490.144748] g4: fff0000000d4a100 g5: 0000000002ad4a68 g6: fff000000a6dc000 g7: 0000010000000000
[  490.259118] o0: 000c0000024005a0 o1: fff00001018a4000 o2: 0000000100028290 o3: 0000000100028290
[  490.373493] o4: fff0000001afe71c o5: 0000000001099c00 sp: fff000000a6deeb1 ret_pc: 000000000065d53c
[  490.492447] RPC: <unmap_page_range+0x53c/0xc60>
[  490.551915] l0: fff00001018f4000 l1: 0000000100028290 l2: fff000000a6df968 l3: fff00001018a4000
[  490.666292] l4: fff00000070a25a0 l5: fff000000a6dfaa8 l6: 0000000000000001 l7: 00000000011605a8
[  490.780668] i0: fff000000a9b0900 i1: fff00001018a6000 i2: fff0000000f99018 i3: fff0000004308290
[  490.895045] i4: fff00001018f4000 i5: 000c0000024005a0 i6: fff000000a6deff1 i7: 000000000065dcd8
[  491.009418] I7: <unmap_single_vma.constprop.0+0x78/0xe0>
[  491.079183] Call Trace:
[  491.111206] [<000000000065dcd8>] unmap_single_vma.constprop.0+0x78/0xe0
[  491.198136] [<000000000065dd9c>] unmap_vmas+0x5c/0x1a0
[  491.265615] [<000000000066a2a4>] exit_mmap+0xc4/0x440
[  491.331950] [<0000000000463d44>] __mmput+0x44/0x140
[  491.396003] [<0000000000463e74>] mmput+0x34/0x60
[  491.456618] [<000000000046a444>] do_exit+0x284/0xaa0
[  491.521816] [<000000000046ae24>] do_group_exit+0x24/0xa0
[  491.591584] [<000000000046aebc>] sys_exit_group+0x1c/0x40
[  491.662496] [<0000000000406174>] linux_sparc_syscall+0x34/0x44
[  491.739127] Disabling lock debugging due to kernel taint
[  491.808896] Caller[000000000065dcd8]: unmap_single_vma.constprop.0+0x78/0xe0
[  491.901543] Caller[000000000065dd9c]: unmap_vmas+0x5c/0x1a0
[  491.974740] Caller[000000000066a2a4]: exit_mmap+0xc4/0x440
[  492.046795] Caller[0000000000463d44]: __mmput+0x44/0x140
[  492.116564] Caller[0000000000463e74]: mmput+0x34/0x60
[  492.182901] Caller[000000000046a444]: do_exit+0x284/0xaa0
[  492.253815] Caller[000000000046ae24]: do_group_exit+0x24/0xa0
[  492.329301] Caller[000000000046aebc]: sys_exit_group+0x1c/0x40
[  492.405935] Caller[0000000000406174]: linux_sparc_syscall+0x34/0x44
[  492.488282] Caller[fff0000102ad4a74]: 0xfff0000102ad4a74
[  492.558054] Instruction DUMP:
[  492.558057]  c6756010 
[  492.596937]  02ff7fd9 
[  492.627825]  c2356018 
[  492.658702] <c25f6008>
[  492.689581]  8610001d 
[  492.720460]  84086001 
[  492.751343]  82007fff 
[  492.782223]  87789401 
[  492.813105]  c258e018 

[  492.894311] Fixing recursive fault but reboot is needed!

Adrian

-- 
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer
`. `'   Physicist
  `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v4 25/36] sparc64: Implement the new page table range API
  2025-08-04  6:58           ` John Paul Adrian Glaubitz
  2025-08-04  7:48             ` John Paul Adrian Glaubitz
@ 2025-08-04  9:38             ` John Paul Adrian Glaubitz
  1 sibling, 0 replies; 11+ messages in thread
From: John Paul Adrian Glaubitz @ 2025-08-04  9:38 UTC (permalink / raw)
  To: Anthony Yznaga, Matthew Wilcox (Oracle), linux-arch
  Cc: linux-mm, linux-kernel, David S. Miller, sparclinux,
	Andreas Larsson, Rod Schnell, Sam James

Hi,


On Mon, 2025-08-04 at 08:58 +0200, John Paul Adrian Glaubitz wrote:
> OK, so v6.8 is fine while v6.9 crashes:
> 
> [   39.788224] Unable to handle kernel NULL pointer dereference
> [   39.862657] tsk->{mm,active_mm}->context = 000000000000004b
> [   39.935941] tsk->{mm,active_mm}->pgd = fff000000aa98000
> [   40.004566]               \|/ ____ \|/
> [   40.004566]               "@'/ .. \`@"
> [   40.004566]               /_| \__/ |_\
> [   40.004566]                  \__U_/
> [   40.197871] (udev-worker)(88): Oops [#1]
> [   40.249329] CPU: 0 PID: 88 Comm: (udev-worker) Tainted: P           O       6.9.0+ #28
> [   40.353415] TSTATE: 0000004411001605 TPC: 0000000000df092c TNPC: 0000000000df0930 Y: 00000000    Tainted: P           O      
> [   40.502105] TPC: <strlen+0x60/0xd4>
> [   40.547844] g0: fff000000a3171a1 g1: 0000000000000000 g2: 0000000000000000 g3: 0000000000000001
> [   40.662224] g4: fff000000aa4dac0 g5: 0000000010000233 g6: fff000000a314000 g7: 0000000000000000
> [   40.776599] o0: 0000000000000010 o1: 0000000000000010 o2: 0000000001010101 o3: 0000000080808080
> [   40.890974] o4: 0000000001010000 o5: 0000000000000000 sp: fff000000a317201 ret_pc: 00000000004d4b08
> [   41.009924] RPC: <module_patient_check_exists.constprop.0+0x48/0x1e0>
> [   41.094557] l0: fff0000100032f40 l1: 0000000000000000 l2: 0000000000000000 l3: 0000000000000000
> [   41.208936] l4: 0000000000000000 l5: 0000000000000000 l6: 0000000000000000 l7: 0000000000000000
> [   41.323311] i0: 00000001000256d8 i1: 0000000001143000 i2: 0000000001143300 i3: 000000000000000b
> [   41.437686] i4: 0000000000000010 i5: fffffffffffffff8 i6: fff000000a3172e1 i7: 00000000004d63f0
> [   41.552062] I7: <load_module+0x550/0x1f00>
> [   41.605811] Call Trace:
> [   41.637838] [<00000000004d63f0>] load_module+0x550/0x1f00
> [   41.708752] [<00000000004d7fac>] init_module_from_file+0x6c/0xa0
> [   41.787670] [<00000000004d81c8>] sys_finit_module+0x188/0x280
> [   41.863158] [<0000000000406174>] linux_sparc_syscall+0x34/0x44
> [   41.939790] Caller[00000000004d63f0]: load_module+0x550/0x1f00
> [   42.016423] Caller[00000000004d7fac]: init_module_from_file+0x6c/0xa0
> [   42.101059] Caller[00000000004d81c8]: sys_finit_module+0x188/0x280
> [   42.182266] Caller[0000000000406174]: linux_sparc_syscall+0x34/0x44
> [   42.264614] Caller[fff000010480e2fc]: 0xfff000010480e2fc
> [   42.334384] Instruction DUMP:
> [   42.334387]  96132080 
> [   42.373269]  19004040 
> [   42.404151]  94132101 
> [   42.435030] <da020000>
> [   42.465914]  9823400a 
> [   42.496793]  808b000b 
> [   42.527674]  024ffffd 
> [   42.558556]  90022004 
> [   42.589437]  8f336018 
> [   42.620318]
> 
> So, the regression was introduced with v6.9. Will bisect this later this week.

Looking closer it seems that the original issue seems to be filesystem corruption and the
consecutive crashes with older kernels might be a result of some corrupted binaries.

Will first try to figure out what commit exactly introduced the ext4 issues on sun4u.

Adrian

-- 
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer
`. `'   Physicist
  `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2025-08-04  9:38 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20230315051444.3229621-1-willy@infradead.org>
2023-03-15  5:14 ` [PATCH v4 24/36] sparc32: Implement the new page table range API Matthew Wilcox (Oracle)
2023-03-15 10:11   ` Mike Rapoport
2023-03-15  5:14 ` [PATCH v4 25/36] sparc64: " Matthew Wilcox (Oracle)
2023-03-15 10:11   ` Mike Rapoport
2025-08-03 12:05   ` John Paul Adrian Glaubitz
2025-08-03 19:08     ` Anthony Yznaga
2025-08-04  5:12       ` John Paul Adrian Glaubitz
2025-08-04  5:36         ` John Paul Adrian Glaubitz
2025-08-04  6:58           ` John Paul Adrian Glaubitz
2025-08-04  7:48             ` John Paul Adrian Glaubitz
2025-08-04  9:38             ` John Paul Adrian Glaubitz

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).