From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id DD8C7FCB61D for ; Fri, 6 Mar 2026 16:17:05 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id EA48E6B00B8; Fri, 6 Mar 2026 11:17:01 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id E46826B00B9; Fri, 6 Mar 2026 11:17:01 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id CB1176B00BA; Fri, 6 Mar 2026 11:17:01 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0011.hostedemail.com [216.40.44.11]) by kanga.kvack.org (Postfix) with ESMTP id B13666B00B8 for ; Fri, 6 Mar 2026 11:17:01 -0500 (EST) Received: from smtpin25.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay04.hostedemail.com (Postfix) with ESMTP id 69A011A060D for ; Fri, 6 Mar 2026 16:17:01 +0000 (UTC) X-FDA: 84516142242.25.C3AA8A5 Received: from mx0b-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) by imf09.hostedemail.com (Postfix) with ESMTP id 0DBFE140013 for ; Fri, 6 Mar 2026 16:16:58 +0000 (UTC) Authentication-Results: imf09.hostedemail.com; dkim=pass header.d=ibm.com header.s=pp1 header.b=Ilx5jLDC; spf=pass (imf09.hostedemail.com: domain of agordeev@linux.ibm.com designates 148.163.158.5 as permitted sender) smtp.mailfrom=agordeev@linux.ibm.com; dmarc=pass (policy=none) header.from=ibm.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1772813819; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=nWjwnS5nyC5gSG8UutEgk3IzL8z2OXssI39FR/MoAKU=; b=vPm6JPexxlrdO5m00Zk+rQBi2bqpBTDZM8Z5/6pRTXvvfPw+5uxjQd0RibvCJNJYB3XcNC HNK1Az26djfo7BTxfzFTZE6V20S/eaRyKrRRGCeonx5XrXMDlbbNmWCQwuzEKdMO6n7o/e 9n0Nc/o243MnEjlCPg2NREw5jno/B8w= ARC-Authentication-Results: i=1; imf09.hostedemail.com; dkim=pass header.d=ibm.com header.s=pp1 header.b=Ilx5jLDC; spf=pass (imf09.hostedemail.com: domain of agordeev@linux.ibm.com designates 148.163.158.5 as permitted sender) smtp.mailfrom=agordeev@linux.ibm.com; dmarc=pass (policy=none) header.from=ibm.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1772813819; a=rsa-sha256; cv=none; b=LNvhrCcNrxa8c6OnoOEKRdWC4/JyD9+4I6MK3nkNCA6EAbt1pnOY/CCGMlt6nOoKLE5pC9 YYBfWsjUwMw+aLCoAcmMCLHf8wCygtHqiMbf5nPoQ0l5ueH6qznP86osxk0hAMiXF4JFlw l9ZljKDH68qtRtyx1NJSiwwUkSfAbBo= Received: from pps.filterd (m0360072.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 626A04G92073025; Fri, 6 Mar 2026 16:16:38 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=nWjwnS5nyC5gSG8Uu tEgk3IzL8z2OXssI39FR/MoAKU=; b=Ilx5jLDC1l9AqYmdmB5yFeL8EnRQXgsIn 5lzxzkg3o3X2YVn7WIzypkTzlSjq/wH0DCcRQe74Fx7jI7AiYqpHepy4PHkvDunB Zm//emKobTl4zKkI7BOz7CUtYA/7uzMkeZrqwWNlxnATkgy8xngyLzG0rEQMQ2h8 MfIj7ZBqvC2zsCPZge7RFv23+UoPOTmMBnX30+61ZYXatrzw+3w2fDD8jamxJbTU 3VTxa7qFRmVhrfv641ngYyzpw9Cw98EE+GCpf84HZ2G2FU0zpiUBdUoQPL7dc82y 1EBaCAFszJaONQpSBuYok99o5tzymyNpxU1hpf/h9kF205fzfrYqw== Received: from ppma23.wdc07v.mail.ibm.com (5d.69.3da9.ip4.static.sl-reverse.com [169.61.105.93]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4ckssn0w15-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 06 Mar 2026 16:16:38 +0000 (GMT) Received: from pps.filterd (ppma23.wdc07v.mail.ibm.com [127.0.0.1]) by ppma23.wdc07v.mail.ibm.com (8.18.1.2/8.18.1.2) with ESMTP id 626DvTMv010309; Fri, 6 Mar 2026 16:16:37 GMT Received: from smtprelay05.fra02v.mail.ibm.com ([9.218.2.225]) by ppma23.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4cmc6kgfvy-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 06 Mar 2026 16:16:37 +0000 Received: from smtpav03.fra02v.mail.ibm.com (smtpav03.fra02v.mail.ibm.com [10.20.54.102]) by smtprelay05.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 626GGXZC46661980 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 6 Mar 2026 16:16:33 GMT Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 6FAC220043; Fri, 6 Mar 2026 16:16:33 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 3563E20040; Fri, 6 Mar 2026 16:16:33 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav03.fra02v.mail.ibm.com (Postfix) with SMTP; Fri, 6 Mar 2026 16:16:33 +0000 (GMT) Received: by tuxmaker.boeblingen.de.ibm.com (Postfix, from userid 55669) id 1C691E078D; Fri, 06 Mar 2026 17:16:33 +0100 (CET) From: Alexander Gordeev To: Madhavan Srinivasan , Michael Ellerman , Pasha Tatashin , Andrew Morton , Vasily Gorbik , Heiko Carstens Cc: linux-s390@vger.kernel.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org, linux-riscv@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linuxppc-dev@lists.ozlabs.org, x86@kernel.org Subject: [PATCH v2 3/4] s390/pgtable: Add s390 support for page table check Date: Fri, 6 Mar 2026 17:16:32 +0100 Message-ID: <4db8a681205bd555298d62441cdcfca43317a35a.1772812343.git.agordeev@linux.ibm.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMzA2MDE1MyBTYWx0ZWRfX1d2OIZjG6Vaz g0Rv9SduxkYPt7UUmGsEi1jwwNqDXHXKWAZGxZwxHmNqqqYLPUwab+S4aJvlG2CKSxcbh5OBhLz kiofMXqIeqVEVQJ+Hiy7wqIEOIq2JyeKt37Ad1Hdb4pbSqra0YyKugiohqSEp4PpkmLnTnclhK5 Fy6oxpW0YBLgf1YaEzeyyzFveRMXSzVxPS+NgwjL/c4MTRKYz7OyIJS9HshwUrm6qGBQYMyn+tZ ct6sLcM76BP621M8V21IvQeGx+fcRcQSGUbugeRemvsSFJwScSatz7ZcefPxExOW16mM3bnnp2h THJTA/4G5MSnUj66ITsQZ+ev8RkThjEixMqeTlz41In2SOBYPRy504DYFbtkoChg61o8oyDXtDI ARxy13S1GBGxouq1FLwk8szju2l51Oakp3Ilma0QuSGZXfqA82O9mm/NzUw7eHUUGwkXzA7bQp1 Bw0Uyh5MG0mmsRnp6Ww== X-Proofpoint-ORIG-GUID: 83ygpnALoePex-sniqGXgjL2kS8s86yy X-Proofpoint-GUID: 83ygpnALoePex-sniqGXgjL2kS8s86yy X-Authority-Analysis: v=2.4 cv=AobjHe9P c=1 sm=1 tr=0 ts=69aafde6 cx=c_pps a=3Bg1Hr4SwmMryq2xdFQyZA==:117 a=3Bg1Hr4SwmMryq2xdFQyZA==:17 a=Yq5XynenixoA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=RzCfie-kr_QcCd8fBx8p:22 a=VnNF1IyMAAAA:8 a=lBuVlAIgDHgG38O_heoA:9 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.51,FMLib:17.12.100.49 definitions=2026-03-06_05,2026-03-06_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 phishscore=0 lowpriorityscore=0 bulkscore=0 impostorscore=0 malwarescore=0 spamscore=0 clxscore=1015 suspectscore=0 adultscore=0 priorityscore=1501 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2602130000 definitions=main-2603060153 X-Rspamd-Queue-Id: 0DBFE140013 X-Rspamd-Server: rspam07 X-Stat-Signature: sikn63ogn6y9gyrmja7uamdcwqz7kmhy X-Rspam-User: X-HE-Tag: 1772813818-859080 X-HE-Meta: U2FsdGVkX1/wgT7ZWqLlGh+6wBGneyrTdi9h8MUloTCfalS8Nr8iWlSOEMO94FerTVHTwTtWjsUe6bet3tLtVwUl5T+ZEf8YAeQu/4G+w7ybmXN7drlG01aPPS1UQ+EN00DcFupI9/fe/bAwENkD1DHyzqc2oEdxCAXyPNN927/wdDbOBqZ6GfU81bsNXTeAabdVi9Me9obmW9bWze4kg1HcZi2gfygf/SkhxMVCWMX+IhxafdWa73fRn8qp8pH1gAyjv+GxrYxxBEoeLVAHvdf02Va9/ZoypQER4LohpJbYbc6cUxZRQaJ14vJ4zWNJMZcHTaQ4jVwDZGPRbCmt11/KBMvd+fTyy5EwSwAlxr5KcNC9/SlTqTJgSOeQs1UkAm/2iT0wPHA8fvnojNK/762AxJXH4bLQfyIZ6RLljLXVl74cusopS3oLhdy1auvICiQmzM2xNL6sma67RPW3Cb7YihS9cClpVOID8FehdjooFRimV+5Ja0UbqhdFUR7QsaVzpFqzK3kG9FUZfEMTBLMkL1vzkFFPRMp+M9fne1+ZVCxT+EEfvo5jWDGB+3CKB6G4i9w8MUwqsl05T5j0OUQ9yAnFatG7B/M32Jq/aCNN+h0aJCPPsn2BIEC0gLsgQtUgqVBPYoqsp0XqNTcC8DNvx7Zcrlb1wVyApxFDjxTh+00BtBlhYbJBvzNsJ05bsEeCkR9CGeg1yceom+CqMgD3zACnIzIUfvY8qA///fhW08/hXK4W1gy2MItDboyvaldbH5WpwtBt2Tf00c6DGKksPLepNtT/pp/Ssv9fPNksPLS+WzWR0F6/BW/FzMLyTNFmb+cShi0/hNoUfyz16+yOyXlNw75zy0TwB1TakXHX3TuMg6+3yZWYdFdGdbi3WOc+6Ldf0IbHgTj8FP/HmVGPj1JWxQpsqp+HSCmylArixVU7FmczvO/z6lDXmK7xsh4C25XhoGxaGRWI7mS s5IVcyWa UNL0JPGQyJs4GS3+/7MY8HjRDVrh9Rm4JWJ2dcf2ZmGklTLLmGqf8FrZ9Kvd+rGeP260TGYHjEQUBFECHsOXzFymBQYIjxAkwV5fVrlFlv7KyT1s8giXK80VYAfOHEC/MGXx/JIAJHtl3yxC/uZoM3LIY9kFm/CofyjGV+c/t+94dbTfiuZNhBvViRog7uxZEZVM3NonuS0vEI7/TCjFL0bv4wuh4f7iIOAAMVQOnSvJczJM= Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: From: Tobias Huschle Add page table check hooks into routines that modify user page tables. Unlike other architectures s390 does not have means to distinguish between kernel and user page table entries. Rely on the fact the page table check infrastructure itself operates on non-init_mm memory spaces only. Use the provided mm_struct to verify that the memory space is not init_mm (aka not the kernel memory space) indeed. That check is supposed to be succeeded already (on some code paths even twice). If the passed memory space by contrast is init_mm that would be an unexpected semantical change in generic code, so do VM_BUG_ON() in such case. Unset _SEGMENT_ENTRY_READ bit to indicate that pmdp_invalidate() was applied against a huge PMD and is going to be updated by set_pmd_at() shortly. The hook pmd_user_accessible_page() should skip such entries until that, otherwise the page table accounting falls apart and BUG_ON() gets hit as result. The invalidated huge PMD entry should not be confused with a PROT_NONE entry as reported by pmd_protnone(), though the entry characteristics exactly match: _SEGMENT_ENTRY_LARGE is set while _SEGMENT_ENTRY_READ is unset. Since pmd_protnone() implementation depends on NUMA_BALANCING configuration option, it should not be used in pmd_user_accessible_page() check, which is expected to be CONFIG_NUMA_BALANCING-agnostic. Nevertheless, an invalidated huge PMD is technically still pmd_protnone() entry and it should not break other code paths once _SEGMENT_ENTRY_READ is unset. As of now, all pmd_protnone() checks are done under page table locks or exercise GUP-fast and HMM code paths, which are expected to be safe against concurrent page table updates. Alternative approach would be using the last remaining unused PMD entry bit 0x800 to indicate that pmdp_invalidate() was called on a PMD. That would allow avoiding collisions with pmd_protnone() handling code paths, but saving the bit is more preferable way to go. Reviewed-by: Gerald Schaefer Signed-off-by: Tobias Huschle Co-developed-by: Alexander Gordeev Signed-off-by: Alexander Gordeev --- arch/s390/Kconfig | 1 + arch/s390/include/asm/pgtable.h | 54 ++++++++++++++++++++++++++++++--- 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index edc927d9e85a..7bda45d30455 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -154,6 +154,7 @@ config S390 select ARCH_SUPPORTS_INT128 if CC_HAS_INT128 && CC_IS_CLANG select ARCH_SUPPORTS_MSEAL_SYSTEM_MAPPINGS select ARCH_SUPPORTS_NUMA_BALANCING + select ARCH_SUPPORTS_PAGE_TABLE_CHECK select ARCH_SUPPORTS_PER_VMA_LOCK select ARCH_USE_BUILTIN_BSWAP select ARCH_USE_CMPXCHG_LOCKREF diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgta= ble.h index 04ec9fee6498..67f5df20a57e 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -16,8 +16,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -1190,6 +1192,7 @@ static inline pte_t ptep_get_and_clear(struct mm_st= ruct *mm, /* At this point the reference through the mapping is still present */ if (mm_is_protected(mm) && pte_present(res)) WARN_ON_ONCE(uv_convert_from_secure_pte(res)); + page_table_check_pte_clear(mm, addr, res); return res; } =20 @@ -1208,6 +1211,7 @@ static inline pte_t ptep_clear_flush(struct vm_area= _struct *vma, /* At this point the reference through the mapping is still present */ if (mm_is_protected(vma->vm_mm) && pte_present(res)) WARN_ON_ONCE(uv_convert_from_secure_pte(res)); + page_table_check_pte_clear(vma->vm_mm, addr, res); return res; } =20 @@ -1231,6 +1235,9 @@ static inline pte_t ptep_get_and_clear_full(struct = mm_struct *mm, } else { res =3D ptep_xchg_lazy(mm, addr, ptep, __pte(_PAGE_INVALID)); } + + page_table_check_pte_clear(mm, addr, res); + /* Nothing to do */ if (!mm_is_protected(mm) || !pte_present(res)) return res; @@ -1327,6 +1334,7 @@ static inline void set_ptes(struct mm_struct *mm, u= nsigned long addr, { if (pte_present(entry)) entry =3D clear_pte_bit(entry, __pgprot(_PAGE_UNUSED)); + page_table_check_ptes_set(mm, addr, ptep, entry, nr); for (;;) { set_pte(ptep, entry); if (--nr =3D=3D 0) @@ -1703,6 +1711,7 @@ static inline int pmdp_clear_flush_young(struct vm_= area_struct *vma, static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp, pmd_t entry) { + page_table_check_pmd_set(mm, addr, pmdp, entry); set_pmd(pmdp, entry); } =20 @@ -1717,7 +1726,11 @@ static inline pmd_t pmd_mkhuge(pmd_t pmd) static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp) { - return pmdp_xchg_direct(mm, addr, pmdp, __pmd(_SEGMENT_ENTRY_EMPTY)); + pmd_t pmd; + + pmd =3D pmdp_xchg_direct(mm, addr, pmdp, __pmd(_SEGMENT_ENTRY_EMPTY)); + page_table_check_pmd_clear(mm, addr, pmd); + return pmd; } =20 #define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR_FULL @@ -1725,12 +1738,17 @@ static inline pmd_t pmdp_huge_get_and_clear_full(= struct vm_area_struct *vma, unsigned long addr, pmd_t *pmdp, int full) { + pmd_t pmd; + if (full) { - pmd_t pmd =3D *pmdp; + pmd =3D *pmdp; set_pmd(pmdp, __pmd(_SEGMENT_ENTRY_EMPTY)); + page_table_check_pmd_clear(vma->vm_mm, addr, pmd); return pmd; } - return pmdp_xchg_lazy(vma->vm_mm, addr, pmdp, __pmd(_SEGMENT_ENTRY_EMPT= Y)); + pmd =3D pmdp_xchg_lazy(vma->vm_mm, addr, pmdp, __pmd(_SEGMENT_ENTRY_EMP= TY)); + page_table_check_pmd_clear(vma->vm_mm, addr, pmd); + return pmd; } =20 #define __HAVE_ARCH_PMDP_HUGE_CLEAR_FLUSH @@ -1748,7 +1766,12 @@ static inline pmd_t pmdp_invalidate(struct vm_area= _struct *vma, =20 VM_WARN_ON_ONCE(!pmd_present(pmd)); pmd =3D set_pmd_bit(pmd, __pgprot(_SEGMENT_ENTRY_INVALID)); - return pmdp_xchg_direct(vma->vm_mm, addr, pmdp, pmd); +#ifdef CONFIG_PAGE_TABLE_CHECK + pmd =3D clear_pmd_bit(pmd, __pgprot(_SEGMENT_ENTRY_READ)); +#endif + page_table_check_pmd_set(vma->vm_mm, addr, pmdp, pmd); + pmd =3D pmdp_xchg_direct(vma->vm_mm, addr, pmdp, pmd); + return pmd; } =20 #define __HAVE_ARCH_PMDP_SET_WRPROTECT @@ -1783,6 +1806,29 @@ static inline int has_transparent_hugepage(void) } #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ =20 +#ifdef CONFIG_PAGE_TABLE_CHECK +static inline bool pte_user_accessible_page(struct mm_struct *mm, unsign= ed long addr, pte_t pte) +{ + VM_BUG_ON(mm =3D=3D &init_mm); + + return pte_present(pte); +} + +static inline bool pmd_user_accessible_page(struct mm_struct *mm, unsign= ed long addr, pmd_t pmd) +{ + VM_BUG_ON(mm =3D=3D &init_mm); + + return pmd_leaf(pmd) && (pmd_val(pmd) & _SEGMENT_ENTRY_READ); +} + +static inline bool pud_user_accessible_page(struct mm_struct *mm, unsign= ed long addr, pud_t pud) +{ + VM_BUG_ON(mm =3D=3D &init_mm); + + return pud_leaf(pud); +} +#endif + /* * 64 bit swap entry format: * A page-table entry has some bits we have to treat in a special way. --=20 2.51.0