From 0031f1c7cf2632a068a80261071b9b1f2d32d836 Mon Sep 17 00:00:00 2001
From: Alexander Gordeev <agordeev@linux.ibm.com>
Date: Fri, 3 Nov 2023 16:40:13 +0100
Subject: [PATCH] s390/mm: use compound page order to distinguish page tables

CRSTs always have size of four pages, while 2KB-size page tables
always occupy a single page. Use that information to distinguish
page tables from CRSTs.

Reviewed-by: Heiko Carstens <hca@linux.ibm.com>
Reviewed-by: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
---
 arch/s390/mm/pgalloc.c | 13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/arch/s390/mm/pgalloc.c b/arch/s390/mm/pgalloc.c
index 5b15b45941c6c..8159f4fade3f5 100644
--- a/arch/s390/mm/pgalloc.c
+++ b/arch/s390/mm/pgalloc.c
@@ -199,20 +199,15 @@ void page_table_free_rcu(struct mmu_gather *tlb, unsigned long *table,
 	mm = tlb->mm;
 	if (mm_alloc_pgste(mm))
 		gmap_unlink(mm, table, vmaddr);
-	table = (unsigned long *)((unsigned long)table | 0x01U);
 	tlb_remove_ptdesc(tlb, table);
 }
 
-void __tlb_remove_table(void *_table)
+void __tlb_remove_table(void *table)
 {
-	struct ptdesc *ptdesc;
-	unsigned int mask;
-	void *table;
+	struct ptdesc *ptdesc = virt_to_ptdesc(table);
+	struct page *page = ptdesc_page(ptdesc);
 
-	mask = (unsigned long)_table & 0x01U;
-	table = (void *)((unsigned long)_table ^ mask);
-	ptdesc = virt_to_ptdesc(table);
-	if (!mask) {
+	if (compound_order(page) == CRST_ALLOC_ORDER) {
 		/* pmd, pud, or p4d */
 		pagetable_free(ptdesc);
 		return;
-- 
2.30.2