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 X-Spam-Level: X-Spam-Status: No, score=-8.1 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_2 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 36F46C4BA13 for ; Wed, 26 Feb 2020 14:12:27 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id BC2A324689 for ; Wed, 26 Feb 2020 14:12:26 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=lca.pw header.i=@lca.pw header.b="rWcvB3Ch" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org BC2A324689 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=lca.pw Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 5939F6B0003; Wed, 26 Feb 2020 09:12:26 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 542FA6B0005; Wed, 26 Feb 2020 09:12:26 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 3BC886B0006; Wed, 26 Feb 2020 09:12:26 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0100.hostedemail.com [216.40.44.100]) by kanga.kvack.org (Postfix) with ESMTP id 1554E6B0003 for ; Wed, 26 Feb 2020 09:12:26 -0500 (EST) Received: from smtpin09.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay01.hostedemail.com (Postfix) with ESMTP id 4393918017FCA for ; Wed, 26 Feb 2020 14:12:25 +0000 (UTC) X-FDA: 76532468250.09.mom75_32130fcac3f54 X-HE-Tag: mom75_32130fcac3f54 X-Filterd-Recvd-Size: 43696 Received: from mail-qt1-f194.google.com (mail-qt1-f194.google.com [209.85.160.194]) by imf28.hostedemail.com (Postfix) with ESMTP for ; Wed, 26 Feb 2020 14:12:23 +0000 (UTC) Received: by mail-qt1-f194.google.com with SMTP id r5so2300514qtt.9 for ; Wed, 26 Feb 2020 06:12:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=lca.pw; s=google; h=message-id:subject:from:to:cc:date:in-reply-to:references :mime-version:content-transfer-encoding; bh=62DaU7w8Jzwvi2LcYDfrb5ELoqeQggQVLyZoZzdYIF0=; b=rWcvB3ChbzzCxhjsRkXwIGu/GTo7njlFvzRCsSW8lMMm97sOvJCBB8yGBE5JoeWJ31 XEFJUxPrzL+8aubEOKhgodlo5lvUk4fWW8CCvChfOo4kAFbQ+jjF5tB6xxx3hI9W4rX3 Id85+OHj79KSqLDnOcgGivnSurvGmHY5Y0wDax4W1DeOv/NGKM2lJPfpBpsaueixcQVu YsMmSBdDql8ep92UT7qNnV5Ujsc5Z4kCk04YWC5r/orXob32oWrMScXUu1R/FK8Mtjks 2xHX0Dfy4GY1Z24Vgd9PfEyO+qFVaVr6ea2Tvk1G0ZGeeAk6DAHzYWPqBrUZjf+bsJil BIxQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:message-id:subject:from:to:cc:date:in-reply-to :references:mime-version:content-transfer-encoding; bh=62DaU7w8Jzwvi2LcYDfrb5ELoqeQggQVLyZoZzdYIF0=; b=sJNi1H119xJujs7psnXJNlyrFG6+7RKrQ8YLyVtmmb+9kzwF+IHX01iDgTjZPbPQpY 70c/jWYjUSS4f+FixZD3wXrK8eREut9EGzUwMJ1YIMNK9aazxYztusXiI29SwZC09Hfz ILkxHflTrg4TZb+P8WwSDMEKX8z+e37DluLD0vklWVU2V0+u8HoWBKRAox9LBrdCpIdB y3covv7UD1AwUSu9aRDj7QO20t76RWEpBKtScx6YU6vhyTxukdpVDOjVLZP4t0+/LOyo iCndw6+TzMqmSDvwuqA+SveJxHLfAm3b4N/NN2ncS7yEQyIZFKlCxUAGoqMBQOpWOORc NF9w== X-Gm-Message-State: APjAAAXv2U25v3E6D0DWlB9xx8iceQYfXIgti7tC+LXlQl8xEnxHN02Q iWvA1d5bgchaYkiLplTWGgiovw== X-Google-Smtp-Source: APXvYqw9aMSIfTjqPLvpJ3bOyXHHZNQ6U+9bhlBH8v5g0ienQKqHKc/G1KSbjjFvDpjZB3+MOQWimg== X-Received: by 2002:aed:256f:: with SMTP id w44mr5262478qtc.331.1582726342954; Wed, 26 Feb 2020 06:12:22 -0800 (PST) Received: from dhcp-41-57.bos.redhat.com (nat-pool-bos-t.redhat.com. [66.187.233.206]) by smtp.gmail.com with ESMTPSA id w9sm1196529qka.71.2020.02.26.06.12.20 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 26 Feb 2020 06:12:22 -0800 (PST) Message-ID: <1582726340.7365.124.camel@lca.pw> Subject: Re: [PATCH V14] mm/debug: Add tests validating architecture page table helpers From: Qian Cai To: Anshuman Khandual , linux-mm@kvack.org Cc: Andrew Morton , Mike Rapoport , Vineet Gupta , Catalin Marinas , Will Deacon , Benjamin Herrenschmidt , Paul Mackerras , Michael Ellerman , Heiko Carstens , Vasily Gorbik , Christian Borntraeger , Thomas Gleixner , Ingo Molnar , Borislav Petkov , "H. Peter Anvin" , "Kirill A . Shutemov" , Paul Walmsley , Palmer Dabbelt , linux-snps-arc@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linuxppc-dev@lists.ozlabs.org, linux-s390@vger.kernel.org, linux-riscv@lists.infradead.org, x86@kernel.org, linux-arch@vger.kernel.org, linux-kernel@vger.kernel.org, Christophe Leroy Date: Wed, 26 Feb 2020 09:12:20 -0500 In-Reply-To: <1582726182.7365.123.camel@lca.pw> References: <1581909460-19148-1-git-send-email-anshuman.khandual@arm.com> <1582726182.7365.123.camel@lca.pw> Content-Type: text/plain; charset="UTF-8" X-Mailer: Evolution 3.22.6 (3.22.6-10.el7) Mime-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: On Wed, 2020-02-26 at 09:09 -0500, Qian Cai wrote: > On Mon, 2020-02-17 at 08:47 +0530, Anshuman Khandual wrote: > > This adds tests which will validate architecture page table helpers a= nd > > other accessors in their compliance with expected generic MM semantic= s. > > This will help various architectures in validating changes to existin= g > > page table helpers or addition of new ones. > >=20 > > This test covers basic page table entry transformations including but= not > > limited to old, young, dirty, clean, write, write protect etc at vari= ous > > level along with populating intermediate entries with next page table= page > > and validating them. > >=20 > > Test page table pages are allocated from system memory with required = size > > and alignments. The mapped pfns at page table levels are derived from= a > > real pfn representing a valid kernel text symbol. This test gets call= ed > > inside kernel_init() right after async_synchronize_full(). > >=20 > > This test gets built and run when CONFIG_DEBUG_VM_PGTABLE is selected= . Any > > architecture, which is willing to subscribe this test will need to se= lect > > ARCH_HAS_DEBUG_VM_PGTABLE. For now this is limited to arc, arm64, x86= , s390 > > and ppc32 platforms where the test is known to build and run successf= ully. > > Going forward, other architectures too can subscribe the test after f= ixing > > any build or runtime problems with their page table helpers. Meanwhil= e for > > better platform coverage, the test can also be enabled with CONFIG_EX= PERT > > even without ARCH_HAS_DEBUG_VM_PGTABLE. > >=20 > > Folks interested in making sure that a given platform's page table he= lpers > > conform to expected generic MM semantics should enable the above conf= ig > > which will just trigger this test during boot. Any non conformity her= e will > > be reported as an warning which would need to be fixed. This test wil= l help > > catch any changes to the agreed upon semantics expected from generic = MM and > > enable platforms to accommodate it thereafter. >=20 > How useful is this that straightly crash the powerpc? And then generate warnings on arm64, [=C2=A0=C2=A0146.634626][=C2=A0=C2=A0=C2=A0=C2=A0T1] debug_vm_pgtable: de= bug_vm_pgtable: Validating architecture page table helpers [=C2=A0=C2=A0146.643995][=C2=A0=C2=A0=C2=A0=C2=A0T1] ------------[ cut he= re ]------------ [=C2=A0=C2=A0146.649350][=C2=A0=C2=A0=C2=A0=C2=A0T1] virt_to_phys used fo= r non-linear address: (____ptrval____) (start_kernel+0x0/0x580) [=C2=A0=C2=A0146.658840][=C2=A0=C2=A0=C2=A0=C2=A0T1] WARNING: CPU: 165 PI= D: 1 at arch/arm64/mm/physaddr.c:15 __virt_to_phys+0x98/0xe0 [=C2=A0=C2=A0146.667976][=C2=A0=C2=A0=C2=A0=C2=A0T1] Modules linked in: [=C2=A0=C2=A0146.671741][=C2=A0=C2=A0=C2=A0=C2=A0T1] CPU: 165 PID: 1 Comm= : swapper/0 Tainted: G=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0L=C2=A0=C2=A0=C2=A0=C2=A05.6.0-rc3-next-20200226 #1 [=C2=A0=C2=A0146.681397][=C2=A0=C2=A0=C2=A0=C2=A0T1] Hardware name: HPE A= pollo 70=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0/C01_APACHE_MB=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= , BIOS L50_5.13_1.11 06/18/2019 [=C2=A0=C2=A0146.691840][=C2=A0=C2=A0=C2=A0=C2=A0T1] pstate: 60400009 (nZ= Cv daif +PAN -UAO) [=C2=A0=C2=A0146.697334][=C2=A0=C2=A0=C2=A0=C2=A0T1] pc : __virt_to_phys+= 0x98/0xe0 [=C2=A0=C2=A0146.702045][=C2=A0=C2=A0=C2=A0=C2=A0T1] lr : __virt_to_phys+= 0x98/0xe0 [=C2=A0=C2=A0146.706753][=C2=A0=C2=A0=C2=A0=C2=A0T1] sp : 18ff00082b7afe1= 0 [=C2=A0=C2=A0146.710766][=C2=A0=C2=A0=C2=A0=C2=A0T1] x29: 18ff00082b7afe3= 0 x28: 0000000000000000=C2=A0 [=C2=A0=C2=A0146.716782][=C2=A0=C2=A0=C2=A0=C2=A0T1] x27: 000000000000000= 0 x26: 0000000000000000=C2=A0 [=C2=A0=C2=A0146.722798][=C2=A0=C2=A0=C2=A0=C2=A0T1] x25: 000000000000000= 0 x24: 0000000000000000=C2=A0 [=C2=A0=C2=A0146.728813][=C2=A0=C2=A0=C2=A0=C2=A0T1] x23: 000000000000000= 0 x22: 0000000000000000=C2=A0 [=C2=A0=C2=A0146.734827][=C2=A0=C2=A0=C2=A0=C2=A0T1] x21: 000000000000000= 0 x20: ffff9000135b4000=C2=A0 [=C2=A0=C2=A0146.740842][=C2=A0=C2=A0=C2=A0=C2=A0T1] x19: ffff90001120085= 8 x18: 0000000000000000=C2=A0 [=C2=A0=C2=A0146.746857][=C2=A0=C2=A0=C2=A0=C2=A0T1] x17: 000000000000000= 0 x16: 0000000000000000=C2=A0 [=C2=A0=C2=A0146.752872][=C2=A0=C2=A0=C2=A0=C2=A0T1] x15: 000000000000000= 0 x14: 3078302b6c656e72=C2=A0 [=C2=A0=C2=A0146.758887][=C2=A0=C2=A0=C2=A0=C2=A0T1] x13: 656b5f747261747= 3 x12: ffff90001369ea90=C2=A0 [=C2=A0=C2=A0146.764901][=C2=A0=C2=A0=C2=A0=C2=A0T1] x11: 00000000000000c= 9 x10: ffff800082b76c0e=C2=A0 [=C2=A0=C2=A0146.770917][=C2=A0=C2=A0=C2=A0=C2=A0T1] x9 : 9d6a2e226040130= 0 x8 : 9d6a2e2260401300=C2=A0 [=C2=A0=C2=A0146.776932][=C2=A0=C2=A0=C2=A0=C2=A0T1] x7 : aaaaaaaaaaaaaaa= a x6 : 0000000000000000=C2=A0 [=C2=A0=C2=A0146.782946][=C2=A0=C2=A0=C2=A0=C2=A0T1] x5 : 000000000000008= 0 x4 : 0000000000000000=C2=A0 [=C2=A0=C2=A0146.788960][=C2=A0=C2=A0=C2=A0=C2=A0T1] x3 : 000000000000001= 0 x2 : 0000000000000008=C2=A0 [=C2=A0=C2=A0146.794975][=C2=A0=C2=A0=C2=A0=C2=A0T1] x1 : 000000000000000= 6 x0 : 0000000000000053=C2=A0 [=C2=A0=C2=A0146.800990][=C2=A0=C2=A0=C2=A0=C2=A0T1] Call trace: [=C2=A0=C2=A0146.804140][=C2=A0=C2=A0=C2=A0=C2=A0T1]=C2=A0=C2=A0__virt_to= _phys+0x98/0xe0 [=C2=A0=C2=A0146.808512][=C2=A0=C2=A0=C2=A0=C2=A0T1]=C2=A0=C2=A0debug_vm_= pgtable+0x74/0x3fc [=C2=A0=C2=A0146.813140][=C2=A0=C2=A0=C2=A0=C2=A0T1]=C2=A0=C2=A0kernel_in= it+0x1c/0x208 [=C2=A0=C2=A0146.817334][=C2=A0=C2=A0=C2=A0=C2=A0T1]=C2=A0=C2=A0ret_from_= fork+0x10/0x18 [=C2=A0=C2=A0146.821608][=C2=A0=C2=A0=C2=A0=C2=A0T1] irq event stamp: 198= 43388 [=C2=A0=C2=A0146.825978][=C2=A0=C2=A0=C2=A0=C2=A0T1] hardirqs last=C2=A0=C2= =A0enabled at (19843387): [] console_unlock+0x8d0/0x970 [=C2=A0=C2=A0146.835553][=C2=A0=C2=A0=C2=A0=C2=A0T1] hardirqs last disabl= ed at (19843388): [] do_debug_exception+0x58/0x2cc [=C2=A0=C2=A0146.845387][=C2=A0=C2=A0=C2=A0=C2=A0T1] softirqs last=C2=A0=C2= =A0enabled at (19843384): [] __do_softirq+0x864/0x900 [=C2=A0=C2=A0146.854796][=C2=A0=C2=A0=C2=A0=C2=A0T1] softirqs last disabl= ed at (19843377): [] irq_exit+0x1c8/0x238 [=C2=A0=C2=A0146.863845][=C2=A0=C2=A0=C2=A0=C2=A0T1] ---[ end trace 31678= d9e845dff89 ]--- >=20 > [=C2=A0=C2=A0=C2=A023.263425][=C2=A0=C2=A0=C2=A0=C2=A0T1] debug_vm_pgta= ble: debug_vm_pgtable: Validating > architecture page table helpers > [=C2=A0=C2=A0=C2=A023.263625][=C2=A0=C2=A0=C2=A0=C2=A0T1] ------------[= cut here ]------------ > [=C2=A0=C2=A0=C2=A023.263649][=C2=A0=C2=A0=C2=A0=C2=A0T1] kernel BUG at= arch/powerpc/mm/pgtable.c:274! > [=C2=A0=C2=A0=C2=A023.263675][=C2=A0=C2=A0=C2=A0=C2=A0T1] Oops: Excepti= on in kernel mode, sig: 5 [#1] > [=C2=A0=C2=A0=C2=A023.263698][=C2=A0=C2=A0=C2=A0=C2=A0T1] LE PAGE_SIZE=3D= 64K MMU=3DRadix SMP NR_CPUS=3D256 > DEBUG_PAGEALLOC NUMA PowerNV > [=C2=A0=C2=A0=C2=A023.263731][=C2=A0=C2=A0=C2=A0=C2=A0T1] Modules linke= d in: > [=C2=A0=C2=A0=C2=A023.263752][=C2=A0=C2=A0=C2=A0=C2=A0T1] CPU: 4 PID: 1= Comm: swapper/0 Not tainted 5.6.0-rc3-next- > 20200226 #1 > [=C2=A0=C2=A0=C2=A023.263776][=C2=A0=C2=A0=C2=A0=C2=A0T1] NIP:=C2=A0=C2= =A0c00000000007308c LR: c00000000103dbd8 CTR: > 0000000000000000 > [=C2=A0=C2=A0=C2=A023.263810][=C2=A0=C2=A0=C2=A0=C2=A0T1] REGS: c000000= 03ddaf9c0 TRAP: 0700=C2=A0=C2=A0=C2=A0Not tainted=C2=A0=C2=A0(5.6.0- > rc3-next-20200226) > [=C2=A0=C2=A0=C2=A023.263846][=C2=A0=C2=A0=C2=A0=C2=A0T1] MSR:=C2=A0=C2= =A09000000000029033 =C2=A0=C2=A0CR: > 22000228=C2=A0=C2=A0XER: 00000000 > [=C2=A0=C2=A0=C2=A023.263888][=C2=A0=C2=A0=C2=A0=C2=A0T1] CFAR: c000000= 000073030 IRQMASK: 0=C2=A0 > [=C2=A0=C2=A0=C2=A023.263888][=C2=A0=C2=A0=C2=A0=C2=A0T1] GPR00: c00000= 000103dbd8 c00000003ddafc50 c000000001656f00 > c000001d7b4ca080=C2=A0 > [=C2=A0=C2=A0=C2=A023.263888][=C2=A0=C2=A0=C2=A0=C2=A0T1] GPR04: 000000= 0000000000 0000000000000009 c00000003ddafc04 > 0000000000000000=C2=A0 > [=C2=A0=C2=A0=C2=A023.263888][=C2=A0=C2=A0=C2=A0=C2=A0T1] GPR08: f0ffff= ffffffffff 0000000000000001 c0000000016279d0 > 00000000000a0000=C2=A0 > [=C2=A0=C2=A0=C2=A023.263888][=C2=A0=C2=A0=C2=A0=C2=A0T1] GPR12: 000000= 0000000000 c000001fffffae00 c000000000010e84 > 0000000000000000=C2=A0 > [=C2=A0=C2=A0=C2=A023.263888][=C2=A0=C2=A0=C2=A0=C2=A0T1] GPR16: 000000= 0000000000 8000000000000105 0000000000000100 > c000000001689a18=C2=A0 > [=C2=A0=C2=A0=C2=A023.263888][=C2=A0=C2=A0=C2=A0=C2=A0T1] GPR20: c00020= 032c660000 c00020032c620000 c000000001716030 > c00020032c600000=C2=A0 > [=C2=A0=C2=A0=C2=A023.263888][=C2=A0=C2=A0=C2=A0=C2=A0T1] GPR24: 000000= 000000000d c000000001716030 c000001d7b4ca080 > c000000001716040=C2=A0 > [=C2=A0=C2=A0=C2=A023.263888][=C2=A0=C2=A0=C2=A0=C2=A0T1] GPR28: c00000= 0001716038 0000000000000000 0000000000000000 > 0000000000000000=C2=A0 > [=C2=A0=C2=A0=C2=A023.264122][=C2=A0=C2=A0=C2=A0=C2=A0T1] NIP [c0000000= 0007308c] assert_pte_locked+0x11c/0x320 > [=C2=A0=C2=A0=C2=A023.264154][=C2=A0=C2=A0=C2=A0=C2=A0T1] LR [c00000000= 103dbd8] debug_vm_pgtable+0x770/0xb7c > [=C2=A0=C2=A0=C2=A023.264186][=C2=A0=C2=A0=C2=A0=C2=A0T1] Call Trace: > [=C2=A0=C2=A0=C2=A023.264206][=C2=A0=C2=A0=C2=A0=C2=A0T1] [c00000003dda= fc50] [c000000000999760] > _raw_spin_unlock+0x30/0x70 (unreliable) > [=C2=A0=C2=A0=C2=A023.264244][=C2=A0=C2=A0=C2=A0=C2=A0T1] [c00000003dda= fcd0] [c00000000103d924] > debug_vm_pgtable+0x4bc/0xb7c > [=C2=A0=C2=A0=C2=A023.264279][=C2=A0=C2=A0=C2=A0=C2=A0T1] [c00000003dda= fdb0] [c000000000010eac] > kernel_init+0x30/0x194 > [=C2=A0=C2=A0=C2=A023.264315][=C2=A0=C2=A0=C2=A0=C2=A0T1] [c00000003dda= fe20] [c00000000000b748] > ret_from_kernel_thread+0x5c/0x74 > [=C2=A0=C2=A0=C2=A023.264349][=C2=A0=C2=A0=C2=A0=C2=A0T1] Instruction d= ump: > [=C2=A0=C2=A0=C2=A023.264368][=C2=A0=C2=A0=C2=A0=C2=A0T1] 60000000 3be0= 0001 7fbef436 eafa0040 7fffc030 3bffffff > 7fff07b4 7ffff038=C2=A0 > [=C2=A0=C2=A0=C2=A023.264409][=C2=A0=C2=A0=C2=A0=C2=A0T1] 7bff1f24 7d37= f82a 7d290074 7929d182 <0b090000> ebdb0000 > e93c0000 7fde4a14=C2=A0 > [=C2=A0=C2=A0=C2=A023.264460][=C2=A0=C2=A0=C2=A0=C2=A0T1] ---[ end trac= e 72d2931022e9ab24 ]--- > [=C2=A0=C2=A0=C2=A023.627311][=C2=A0=C2=A0=C2=A0=C2=A0T1]=C2=A0 > [=C2=A0=C2=A0=C2=A024.627407][=C2=A0=C2=A0=C2=A0=C2=A0T1] Kernel panic = - not syncing: Fatal exception > [=C2=A0=C2=A0=C2=A026.5 >=20 > >=20 > > Cc: Andrew Morton > > Cc: Mike Rapoport > > Cc: Vineet Gupta > > Cc: Catalin Marinas > > Cc: Will Deacon > > Cc: Benjamin Herrenschmidt > > Cc: Paul Mackerras > > Cc: Michael Ellerman > > Cc: Heiko Carstens > > Cc: Vasily Gorbik > > Cc: Christian Borntraeger > > Cc: Thomas Gleixner > > Cc: Ingo Molnar > > Cc: Borislav Petkov > > Cc: "H. Peter Anvin" > > Cc: Kirill A. Shutemov > > Cc: Paul Walmsley > > Cc: Palmer Dabbelt > > Cc: linux-snps-arc@lists.infradead.org > > Cc: linux-arm-kernel@lists.infradead.org > > Cc: linuxppc-dev@lists.ozlabs.org > > Cc: linux-s390@vger.kernel.org > > Cc: linux-riscv@lists.infradead.org > > Cc: x86@kernel.org > > Cc: linux-arch@vger.kernel.org > > Cc: linux-kernel@vger.kernel.org > >=20 > > Suggested-by: Catalin Marinas > > Reviewed-by: Ingo Molnar > > Tested-by: Gerald Schaefer # s390 > > Tested-by: Christophe Leroy # ppc32 > > Signed-off-by: Andrew Morton > > Signed-off-by: Christophe Leroy > > Signed-off-by: Anshuman Khandual > > --- > > This adds a test validation for architecture exported page table help= ers. > > Patch adds basic transformation tests at various levels of the page t= able. > >=20 > > This test was originally suggested by Catalin during arm64 THP migrat= ion > > RFC discussion earlier. Going forward it can include more specific te= sts > > with respect to various generic MM functions like THP, HugeTLB etc an= d > > platform specific tests. > >=20 > > https://lore.kernel.org/linux-mm/20190628102003.GA56463@arrakis.emea.= arm.com/ > >=20 > > Needs to be applied on linux V5.6-rc2 > >=20 > > Changes in V14: > >=20 > > - Disabled DEBUG_VM_PGFLAGS for IA64 and ARM (32 Bit) per Andrew and = Christophe > > - Updated DEBUG_VM_PGFLAGS documentation wrt EXPERT and disabled plat= forms > > - Updated RANDOM_[OR|NZ]VALUE open encodings with GENMASK() per Catal= in > > - Updated s390 constraint bits from 12 to 4 (S390_MASK_BITS) per Gera= ld > > - Updated in-code documentation for RANDOM_ORVALUE per Gerald > > - Updated pxx_basic_tests() to use invert functions first per Catalin > > - Dropped ARCH_HAS_4LEVEL_HACK check from pud_basic_tests() > > - Replaced __ARCH_HAS_[4|5]LEVEL_HACK with __PAGETABLE_[PUD|P4D]_FOLD= ED per Catalin > > - Trimmed the CC list on the commit message per Catalin > >=20 > > Changes in V13: (https://patchwork.kernel.org/project/linux-mm/list/?= series=3D237125) > >=20 > > - Subscribed s390 platform and updated debug-vm-pgtable/arch-support.= txt per Gerald > > - Dropped keyword 'extern' from debug_vm_pgtable() declaration per Ch= ristophe > > - Moved debug_vm_pgtable() declarations to per Chri= stophe > > - Moved debug_vm_pgtable() call site into kernel_init() per Christoph= e > > - Changed CONFIG_DEBUG_VM_PGTABLE rules per Christophe > > - Updated commit to include new supported platforms and changed confi= g selection > >=20 > > Changes in V12: (https://patchwork.kernel.org/project/linux-mm/list/?= series=3D233905) > >=20 > > - Replaced __mmdrop() with mmdrop() > > - Enable ARCH_HAS_DEBUG_VM_PGTABLE on X86 for non CONFIG_X86_PAE plat= forms as the > > test procedure interfere with pre-allocated PMDs attached to the PG= D resulting > > in runtime failures with VM_BUG_ON() > >=20 > > Changes in V11: (https://patchwork.kernel.org/project/linux-mm/list/?= series=3D221135) > >=20 > > - Rebased the patch on V5.4 > >=20 > > Changes in V10: (https://patchwork.kernel.org/project/linux-mm/list/?= series=3D205529) > >=20 > > - Always enable DEBUG_VM_PGTABLE when DEBUG_VM is enabled per Ingo > > - Added tags from Ingo > >=20 > > Changes in V9: (https://patchwork.kernel.org/project/linux-mm/list/?s= eries=3D201429) > >=20 > > - Changed feature support enumeration for powerpc platforms per Chris= tophe > > - Changed config wrapper for basic_[pmd|pud]_tests() to enable ARC pl= atform > > - Enabled the test on ARC platform > >=20 > > Changes in V8: (https://patchwork.kernel.org/project/linux-mm/list/?s= eries=3D194297) > >=20 > > - Enabled ARCH_HAS_DEBUG_VM_PGTABLE on PPC32 platform per Christophe > > - Updated feature documentation as DEBUG_VM_PGTABLE is now enabled on= PPC32 platform > > - Moved ARCH_HAS_DEBUG_VM_PGTABLE earlier to indent it with DEBUG_VM = per Christophe > > - Added an information message in debug_vm_pgtable() per Christophe > > - Dropped random_vaddr boundary condition checks per Christophe and Q= ian > > - Replaced virt_addr_valid() check with pfn_valid() check in debug_vm= _pgtable() > > - Slightly changed pr_fmt(fmt) information > >=20 > > Changes in V7: (https://patchwork.kernel.org/project/linux-mm/list/?s= eries=3D193051) > >=20 > > - Memory allocation and free routines for mapped pages have been drop= ed > > - Mapped pfns are derived from standard kernel text symbol per Matthe= w > > - Moved debug_vm_pgtaable() after page_alloc_init_late() per Michal a= nd Qian=20 > > - Updated the commit message per Michal > > - Updated W=3D1 GCC warning problem on x86 per Qian Cai > > - Addition of new alloc_contig_pages() helper has been submitted sepa= rately > >=20 > > Changes in V6: (https://patchwork.kernel.org/project/linux-mm/list/?s= eries=3D187589) > >=20 > > - Moved alloc_gigantic_page_order() into mm/page_alloc.c per Michal > > - Moved alloc_gigantic_page_order() within CONFIG_CONTIG_ALLOC in the= test > > - Folded Andrew's include/asm-generic/pgtable.h fix into the test pat= ch 2/2 > >=20 > > Changes in V5: (https://patchwork.kernel.org/project/linux-mm/list/?s= eries=3D185991) > >=20 > > - Redefined and moved X86 mm_p4d_folded() into a different header per= Kirill/Ingo > > - Updated the config option comment per Ingo and dropped 'kernel modu= le' reference > > - Updated the commit message and dropped 'kernel module' reference > > - Changed DEBUG_ARCH_PGTABLE_TEST into DEBUG_VM_PGTABLE per Ingo > > - Moved config option from mm/Kconfig.debug into lib/Kconfig.debug > > - Renamed core test function arch_pgtable_tests() as debug_vm_pgtable= () > > - Renamed mm/arch_pgtable_test.c as mm/debug_vm_pgtable.c > > - debug_vm_pgtable() gets called from kernel_init_freeable() after in= it_mm_internals() > > - Added an entry in Documentation/features/debug/ per Ingo > > - Enabled the test on arm64 and x86 platforms for now > >=20 > > Changes in V4: (https://patchwork.kernel.org/project/linux-mm/list/?s= eries=3D183465) > >=20 > > - Disable DEBUG_ARCH_PGTABLE_TEST for ARM and IA64 platforms > >=20 > > Changes in V3: (https://lore.kernel.org/patchwork/project/lkml/list/?= series=3D411216) > >=20 > > - Changed test trigger from module format into late_initcall() > > - Marked all functions with __init to be freed after completion > > - Changed all __PGTABLE_PXX_FOLDED checks as mm_pxx_folded() > > - Folded in PPC32 fixes from Christophe > >=20 > > Changes in V2: > >=20 > > https://lore.kernel.org/linux-mm/1568268173-31302-1-git-send-email-an= shuman.khandual@arm.com/T/#t > >=20 > > - Fixed small typo error in MODULE_DESCRIPTION() > > - Fixed m64k build problems for lvalue concerns in pmd_xxx_tests() > > - Fixed dynamic page table level folding problems on x86 as per Kirri= l > > - Fixed second pointers during pxx_populate_tests() per Kirill and Ge= rald > > - Allocate and free pte table with pte_alloc_one/pte_free per Kirill > > - Modified pxx_clear_tests() to accommodate s390 lower 12 bits situat= ion > > - Changed RANDOM_NZVALUE value from 0xbe to 0xff > > - Changed allocation, usage, free sequence for saved_ptep > > - Renamed VMA_FLAGS as VMFLAGS > > - Implemented a new method for random vaddr generation > > - Implemented some other cleanups > > - Dropped extern reference to mm_alloc() > > - Created and exported new alloc_gigantic_page_order() > > - Dropped the custom allocator and used new alloc_gigantic_page_order= () > >=20 > > Changes in V1: > >=20 > > https://lore.kernel.org/linux-mm/1567497706-8649-1-git-send-email-ans= human.khandual@arm.com/ > >=20 > > - Added fallback mechanism for PMD aligned memory allocation failure > >=20 > > Changes in RFC V2: > >=20 > > https://lore.kernel.org/linux-mm/1565335998-22553-1-git-send-email-an= shuman.khandual@arm.com/T/#u > >=20 > > - Moved test module and it's config from lib/ to mm/ > > - Renamed config TEST_ARCH_PGTABLE as DEBUG_ARCH_PGTABLE_TEST > > - Renamed file from test_arch_pgtable.c to arch_pgtable_test.c > > - Added relevant MODULE_DESCRIPTION() and MODULE_AUTHOR() details > > - Dropped loadable module config option > > - Basic tests now use memory blocks with required size and alignment > > - PUD aligned memory block gets allocated with alloc_contig_range() > > - If PUD aligned memory could not be allocated it falls back on PMD a= ligned > > memory block from page allocator and pud_* tests are skipped > > - Clear and populate tests now operate on real in memory page table e= ntries > > - Dummy mm_struct gets allocated with mm_alloc() > > - Dummy page table entries get allocated with [pud|pmd|pte]_alloc_[ma= p]() > > - Simplified [p4d|pgd]_basic_tests(), now has random values in the en= tries > >=20 > > Original RFC V1: > >=20 > > https://lore.kernel.org/linux-mm/1564037723-26676-1-git-send-email-an= shuman.khandual@arm.com/ > >=20 > >=20 > > .../debug/debug-vm-pgtable/arch-support.txt | 35 ++ > > arch/arc/Kconfig | 1 + > > arch/arm64/Kconfig | 1 + > > arch/powerpc/Kconfig | 1 + > > arch/s390/Kconfig | 1 + > > arch/x86/Kconfig | 1 + > > arch/x86/include/asm/pgtable_64.h | 6 + > > include/linux/mmdebug.h | 5 + > > init/main.c | 2 + > > lib/Kconfig.debug | 26 ++ > > mm/Makefile | 1 + > > mm/debug_vm_pgtable.c | 389 ++++++++++++++++= ++ > > 12 files changed, 469 insertions(+) > > create mode 100644 Documentation/features/debug/debug-vm-pgtable/arc= h-support.txt > > create mode 100644 mm/debug_vm_pgtable.c > >=20 > > diff --git a/Documentation/features/debug/debug-vm-pgtable/arch-suppo= rt.txt b/Documentation/features/debug/debug-vm-pgtable/arch-support.txt > > new file mode 100644 > > index 000000000000..64d0f9b15c49 > > --- /dev/null > > +++ b/Documentation/features/debug/debug-vm-pgtable/arch-support.txt > > @@ -0,0 +1,35 @@ > > +# > > +# Feature name: debug-vm-pgtable > > +# Kconfig: ARCH_HAS_DEBUG_VM_PGTABLE > > +# description: arch supports pgtable tests for semantics c= ompliance > > +# > > + ----------------------- > > + | arch |status| > > + ----------------------- > > + | alpha: | TODO | > > + | arc: | ok | > > + | arm: | TODO | > > + | arm64: | ok | > > + | c6x: | TODO | > > + | csky: | TODO | > > + | h8300: | TODO | > > + | hexagon: | TODO | > > + | ia64: | TODO | > > + | m68k: | TODO | > > + | microblaze: | TODO | > > + | mips: | TODO | > > + | nds32: | TODO | > > + | nios2: | TODO | > > + | openrisc: | TODO | > > + | parisc: | TODO | > > + | powerpc/32: | ok | > > + | powerpc/64: | TODO | > > + | riscv: | TODO | > > + | s390: | ok | > > + | sh: | TODO | > > + | sparc: | TODO | > > + | um: | TODO | > > + | unicore32: | TODO | > > + | x86: | ok | > > + | xtensa: | TODO | > > + ----------------------- > > diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig > > index ff2a393b635c..3e72e6cf0e42 100644 > > --- a/arch/arc/Kconfig > > +++ b/arch/arc/Kconfig > > @@ -6,6 +6,7 @@ > > config ARC > > def_bool y > > select ARC_TIMERS > > + select ARCH_HAS_DEBUG_VM_PGTABLE > > select ARCH_HAS_DMA_PREP_COHERENT > > select ARCH_HAS_PTE_SPECIAL > > select ARCH_HAS_SETUP_DMA_OPS > > diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig > > index 0b30e884e088..aaf8ba415145 100644 > > --- a/arch/arm64/Kconfig > > +++ b/arch/arm64/Kconfig > > @@ -11,6 +11,7 @@ config ARM64 > > select ACPI_PPTT if ACPI > > select ARCH_CLOCKSOURCE_DATA > > select ARCH_HAS_DEBUG_VIRTUAL > > + select ARCH_HAS_DEBUG_VM_PGTABLE > > select ARCH_HAS_DEVMEM_IS_ALLOWED > > select ARCH_HAS_DMA_PREP_COHERENT > > select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI > > diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig > > index 497b7d0b2d7e..8d5ae14c5d4c 100644 > > --- a/arch/powerpc/Kconfig > > +++ b/arch/powerpc/Kconfig > > @@ -116,6 +116,7 @@ config PPC > > # > > select ARCH_32BIT_OFF_T if PPC32 > > select ARCH_HAS_DEBUG_VIRTUAL > > + select ARCH_HAS_DEBUG_VM_PGTABLE if PPC32 > > select ARCH_HAS_DEVMEM_IS_ALLOWED > > select ARCH_HAS_ELF_RANDOMIZE > > select ARCH_HAS_FORTIFY_SOURCE > > diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig > > index 8abe77536d9d..af284dbb07e7 100644 > > --- a/arch/s390/Kconfig > > +++ b/arch/s390/Kconfig > > @@ -59,6 +59,7 @@ config KASAN_SHADOW_OFFSET > > config S390 > > def_bool y > > select ARCH_BINFMT_ELF_STATE > > + select ARCH_HAS_DEBUG_VM_PGTABLE > > select ARCH_HAS_DEVMEM_IS_ALLOWED > > select ARCH_HAS_ELF_RANDOMIZE > > select ARCH_HAS_FORTIFY_SOURCE > > diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig > > index beea77046f9b..df8a19e52e82 100644 > > --- a/arch/x86/Kconfig > > +++ b/arch/x86/Kconfig > > @@ -61,6 +61,7 @@ config X86 > > select ARCH_CLOCKSOURCE_INIT > > select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI > > select ARCH_HAS_DEBUG_VIRTUAL > > + select ARCH_HAS_DEBUG_VM_PGTABLE if !X86_PAE > > select ARCH_HAS_DEVMEM_IS_ALLOWED > > select ARCH_HAS_ELF_RANDOMIZE > > select ARCH_HAS_FAST_MULTIPLIER > > diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm= /pgtable_64.h > > index 0b6c4042942a..fb0e76d254b3 100644 > > --- a/arch/x86/include/asm/pgtable_64.h > > +++ b/arch/x86/include/asm/pgtable_64.h > > @@ -53,6 +53,12 @@ static inline void sync_initial_page_table(void) {= } > > =20 > > struct mm_struct; > > =20 > > +#define mm_p4d_folded mm_p4d_folded > > +static inline bool mm_p4d_folded(struct mm_struct *mm) > > +{ > > + return !pgtable_l5_enabled(); > > +} > > + > > void set_pte_vaddr_p4d(p4d_t *p4d_page, unsigned long vaddr, pte_t n= ew_pte); > > void set_pte_vaddr_pud(pud_t *pud_page, unsigned long vaddr, pte_t n= ew_pte); > > =20 > > diff --git a/include/linux/mmdebug.h b/include/linux/mmdebug.h > > index 2ad72d2c8cc5..5339aa14b749 100644 > > --- a/include/linux/mmdebug.h > > +++ b/include/linux/mmdebug.h > > @@ -64,4 +64,9 @@ void dump_mm(const struct mm_struct *mm); > > #define VM_BUG_ON_PGFLAGS(cond, page) BUILD_BUG_ON_INVALID(cond) > > #endif > > =20 > > +#ifdef CONFIG_DEBUG_VM_PGTABLE > > +void debug_vm_pgtable(void); > > +#else > > +static inline void debug_vm_pgtable(void) { } > > +#endif > > #endif > > diff --git a/init/main.c b/init/main.c > > index cc0ee4873419..adf37e8b1d69 100644 > > --- a/init/main.c > > +++ b/init/main.c > > @@ -94,6 +94,7 @@ > > #include > > #include > > #include > > +#include > > =20 > > #include > > #include > > @@ -1323,6 +1324,7 @@ static int __ref kernel_init(void *unused) > > kernel_init_freeable(); > > /* need to finish all async __init code before freeing the memory *= / > > async_synchronize_full(); > > + debug_vm_pgtable(); > > ftrace_free_init_mem(); > > free_initmem(); > > mark_readonly(); > > diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug > > index 69def4a9df00..1b5bd9f7c967 100644 > > --- a/lib/Kconfig.debug > > +++ b/lib/Kconfig.debug > > @@ -653,6 +653,12 @@ config SCHED_STACK_END_CHECK > > data corruption or a sporadic crash at a later stage once the reg= ion > > is examined. The runtime overhead introduced is minimal. > > =20 > > +config ARCH_HAS_DEBUG_VM_PGTABLE > > + bool > > + help > > + An architecture should select this when it can successfully > > + build and run DEBUG_VM_PGTABLE. > > + > > config DEBUG_VM > > bool "Debug VM" > > depends on DEBUG_KERNEL > > @@ -688,6 +694,26 @@ config DEBUG_VM_PGFLAGS > > =20 > > If unsure, say N. > > =20 > > +config DEBUG_VM_PGTABLE > > + bool "Debug arch page table for semantics compliance" > > + depends on MMU > > + depends on !IA64 && !ARM > > + depends on ARCH_HAS_DEBUG_VM_PGTABLE || EXPERT > > + default n if !ARCH_HAS_DEBUG_VM_PGTABLE > > + default y if DEBUG_VM > > + help > > + This option provides a debug method which can be used to test > > + architecture page table helper functions on various platforms in > > + verifying if they comply with expected generic MM semantics. This > > + will help architecture code in making sure that any changes or > > + new additions of these helpers still conform to expected > > + semantics of the generic MM. Platforms will have to opt in for > > + this through ARCH_HAS_DEBUG_VM_PGTABLE. Although it can also be > > + enabled through EXPERT without requiring code change. This test > > + is disabled on IA64 and ARM platforms where it fails to build. > > + > > + If unsure, say N. > > + > > config ARCH_HAS_DEBUG_VIRTUAL > > bool > > =20 > > diff --git a/mm/Makefile b/mm/Makefile > > index 272e66039e70..b0692e6a4b58 100644 > > --- a/mm/Makefile > > +++ b/mm/Makefile > > @@ -87,6 +87,7 @@ obj-$(CONFIG_HWPOISON_INJECT) +=3D hwpoison-inject.= o > > obj-$(CONFIG_DEBUG_KMEMLEAK) +=3D kmemleak.o > > obj-$(CONFIG_DEBUG_KMEMLEAK_TEST) +=3D kmemleak-test.o > > obj-$(CONFIG_DEBUG_RODATA_TEST) +=3D rodata_test.o > > +obj-$(CONFIG_DEBUG_VM_PGTABLE) +=3D debug_vm_pgtable.o > > obj-$(CONFIG_PAGE_OWNER) +=3D page_owner.o > > obj-$(CONFIG_CLEANCACHE) +=3D cleancache.o > > obj-$(CONFIG_MEMORY_ISOLATION) +=3D page_isolation.o > > diff --git a/mm/debug_vm_pgtable.c b/mm/debug_vm_pgtable.c > > new file mode 100644 > > index 000000000000..70bf8ed8fd51 > > --- /dev/null > > +++ b/mm/debug_vm_pgtable.c > > @@ -0,0 +1,389 @@ > > +// SPDX-License-Identifier: GPL-2.0-only > > +/* > > + * This kernel test validates architecture page table helpers and > > + * accessors and helps in verifying their continued compliance with > > + * expected generic MM semantics. > > + * > > + * Copyright (C) 2019 ARM Ltd. > > + * > > + * Author: Anshuman Khandual > > + */ > > +#define pr_fmt(fmt) "debug_vm_pgtable: %s: " fmt, __func__ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +/* > > + * Basic operations > > + * > > + * mkold(entry) =3D An old and not a young entry > > + * mkyoung(entry) =3D A young and not an old entry > > + * mkdirty(entry) =3D A dirty and not a clean entry > > + * mkclean(entry) =3D A clean and not a dirty entry > > + * mkwrite(entry) =3D A write and not a write protected entry > > + * wrprotect(entry) =3D A write protected and not a write entry > > + * pxx_bad(entry) =3D A mapped and non-table entry > > + * pxx_same(entry1, entry2) =3D Both entries hold the exact same val= ue > > + */ > > +#define VMFLAGS (VM_READ|VM_WRITE|VM_EXEC) > > + > > +/* > > + * On s390 platform, the lower 4 bits are used to identify given pag= e table > > + * entry type. But these bits might affect the ability to clear entr= ies with > > + * pxx_clear() because of how dynamic page table folding works on s3= 90. So > > + * while loading up the entries do not change the lower 4 bits. It d= oes not > > + * have affect any other platform. > > + */ > > +#define S390_MASK_BITS 4 > > +#define RANDOM_ORVALUE GENMASK(BITS_PER_LONG - 1, S390_MASK_BITS) > > +#define RANDOM_NZVALUE GENMASK(7, 0) > > + > > +static void __init pte_basic_tests(unsigned long pfn, pgprot_t prot) > > +{ > > + pte_t pte =3D pfn_pte(pfn, prot); > > + > > + WARN_ON(!pte_same(pte, pte)); > > + WARN_ON(!pte_young(pte_mkyoung(pte_mkold(pte)))); > > + WARN_ON(!pte_dirty(pte_mkdirty(pte_mkclean(pte)))); > > + WARN_ON(!pte_write(pte_mkwrite(pte_wrprotect(pte)))); > > + WARN_ON(pte_young(pte_mkold(pte_mkyoung(pte)))); > > + WARN_ON(pte_dirty(pte_mkclean(pte_mkdirty(pte)))); > > + WARN_ON(pte_write(pte_wrprotect(pte_mkwrite(pte)))); > > +} > > + > > +#ifdef CONFIG_TRANSPARENT_HUGEPAGE > > +static void __init pmd_basic_tests(unsigned long pfn, pgprot_t prot) > > +{ > > + pmd_t pmd =3D pfn_pmd(pfn, prot); > > + > > + WARN_ON(!pmd_same(pmd, pmd)); > > + WARN_ON(!pmd_young(pmd_mkyoung(pmd_mkold(pmd)))); > > + WARN_ON(!pmd_dirty(pmd_mkdirty(pmd_mkclean(pmd)))); > > + WARN_ON(!pmd_write(pmd_mkwrite(pmd_wrprotect(pmd)))); > > + WARN_ON(pmd_young(pmd_mkold(pmd_mkyoung(pmd)))); > > + WARN_ON(pmd_dirty(pmd_mkclean(pmd_mkdirty(pmd)))); > > + WARN_ON(pmd_write(pmd_wrprotect(pmd_mkwrite(pmd)))); > > + /* > > + * A huge page does not point to next level page table > > + * entry. Hence this must qualify as pmd_bad(). > > + */ > > + WARN_ON(!pmd_bad(pmd_mkhuge(pmd))); > > +} > > + > > +#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD > > +static void __init pud_basic_tests(unsigned long pfn, pgprot_t prot) > > +{ > > + pud_t pud =3D pfn_pud(pfn, prot); > > + > > + WARN_ON(!pud_same(pud, pud)); > > + WARN_ON(!pud_young(pud_mkyoung(pud_mkold(pud)))); > > + WARN_ON(!pud_write(pud_mkwrite(pud_wrprotect(pud)))); > > + WARN_ON(pud_write(pud_wrprotect(pud_mkwrite(pud)))); > > + WARN_ON(pud_young(pud_mkold(pud_mkyoung(pud)))); > > + > > + if (mm_pmd_folded(mm)) > > + return; > > + > > + /* > > + * A huge page does not point to next level page table > > + * entry. Hence this must qualify as pud_bad(). > > + */ > > + WARN_ON(!pud_bad(pud_mkhuge(pud))); > > +} > > +#else > > +static void __init pud_basic_tests(unsigned long pfn, pgprot_t prot)= { } > > +#endif > > +#else > > +static void __init pmd_basic_tests(unsigned long pfn, pgprot_t prot)= { } > > +static void __init pud_basic_tests(unsigned long pfn, pgprot_t prot)= { } > > +#endif > > + > > +static void __init p4d_basic_tests(unsigned long pfn, pgprot_t prot) > > +{ > > + p4d_t p4d; > > + > > + memset(&p4d, RANDOM_NZVALUE, sizeof(p4d_t)); > > + WARN_ON(!p4d_same(p4d, p4d)); > > +} > > + > > +static void __init pgd_basic_tests(unsigned long pfn, pgprot_t prot) > > +{ > > + pgd_t pgd; > > + > > + memset(&pgd, RANDOM_NZVALUE, sizeof(pgd_t)); > > + WARN_ON(!pgd_same(pgd, pgd)); > > +} > > + > > +#ifndef __PAGETABLE_PUD_FOLDED > > +static void __init pud_clear_tests(struct mm_struct *mm, pud_t *pudp= ) > > +{ > > + pud_t pud =3D READ_ONCE(*pudp); > > + > > + if (mm_pmd_folded(mm)) > > + return; > > + > > + pud =3D __pud(pud_val(pud) | RANDOM_ORVALUE); > > + WRITE_ONCE(*pudp, pud); > > + pud_clear(pudp); > > + pud =3D READ_ONCE(*pudp); > > + WARN_ON(!pud_none(pud)); > > +} > > + > > +static void __init pud_populate_tests(struct mm_struct *mm, pud_t *p= udp, > > + pmd_t *pmdp) > > +{ > > + pud_t pud; > > + > > + if (mm_pmd_folded(mm)) > > + return; > > + /* > > + * This entry points to next level page table page. > > + * Hence this must not qualify as pud_bad(). > > + */ > > + pmd_clear(pmdp); > > + pud_clear(pudp); > > + pud_populate(mm, pudp, pmdp); > > + pud =3D READ_ONCE(*pudp); > > + WARN_ON(pud_bad(pud)); > > +} > > +#else > > +static void __init pud_clear_tests(struct mm_struct *mm, pud_t *pudp= ) { } > > +static void __init pud_populate_tests(struct mm_struct *mm, pud_t *p= udp, > > + pmd_t *pmdp) > > +{ > > +} > > +#endif > > + > > +#ifndef __PAGETABLE_P4D_FOLDED > > +static void __init p4d_clear_tests(struct mm_struct *mm, p4d_t *p4dp= ) > > +{ > > + p4d_t p4d =3D READ_ONCE(*p4dp); > > + > > + if (mm_pud_folded(mm)) > > + return; > > + > > + p4d =3D __p4d(p4d_val(p4d) | RANDOM_ORVALUE); > > + WRITE_ONCE(*p4dp, p4d); > > + p4d_clear(p4dp); > > + p4d =3D READ_ONCE(*p4dp); > > + WARN_ON(!p4d_none(p4d)); > > +} > > + > > +static void __init p4d_populate_tests(struct mm_struct *mm, p4d_t *p= 4dp, > > + pud_t *pudp) > > +{ > > + p4d_t p4d; > > + > > + if (mm_pud_folded(mm)) > > + return; > > + > > + /* > > + * This entry points to next level page table page. > > + * Hence this must not qualify as p4d_bad(). > > + */ > > + pud_clear(pudp); > > + p4d_clear(p4dp); > > + p4d_populate(mm, p4dp, pudp); > > + p4d =3D READ_ONCE(*p4dp); > > + WARN_ON(p4d_bad(p4d)); > > +} > > + > > +static void __init pgd_clear_tests(struct mm_struct *mm, pgd_t *pgdp= ) > > +{ > > + pgd_t pgd =3D READ_ONCE(*pgdp); > > + > > + if (mm_p4d_folded(mm)) > > + return; > > + > > + pgd =3D __pgd(pgd_val(pgd) | RANDOM_ORVALUE); > > + WRITE_ONCE(*pgdp, pgd); > > + pgd_clear(pgdp); > > + pgd =3D READ_ONCE(*pgdp); > > + WARN_ON(!pgd_none(pgd)); > > +} > > + > > +static void __init pgd_populate_tests(struct mm_struct *mm, pgd_t *p= gdp, > > + p4d_t *p4dp) > > +{ > > + pgd_t pgd; > > + > > + if (mm_p4d_folded(mm)) > > + return; > > + > > + /* > > + * This entry points to next level page table page. > > + * Hence this must not qualify as pgd_bad(). > > + */ > > + p4d_clear(p4dp); > > + pgd_clear(pgdp); > > + pgd_populate(mm, pgdp, p4dp); > > + pgd =3D READ_ONCE(*pgdp); > > + WARN_ON(pgd_bad(pgd)); > > +} > > +#else > > +static void __init p4d_clear_tests(struct mm_struct *mm, p4d_t *p4dp= ) { } > > +static void __init pgd_clear_tests(struct mm_struct *mm, pgd_t *pgdp= ) { } > > +static void __init p4d_populate_tests(struct mm_struct *mm, p4d_t *p= 4dp, > > + pud_t *pudp) > > +{ > > +} > > +static void __init pgd_populate_tests(struct mm_struct *mm, pgd_t *p= gdp, > > + p4d_t *p4dp) > > +{ > > +} > > +#endif > > + > > +static void __init pte_clear_tests(struct mm_struct *mm, pte_t *ptep= ) > > +{ > > + pte_t pte =3D READ_ONCE(*ptep); > > + > > + pte =3D __pte(pte_val(pte) | RANDOM_ORVALUE); > > + WRITE_ONCE(*ptep, pte); > > + pte_clear(mm, 0, ptep); > > + pte =3D READ_ONCE(*ptep); > > + WARN_ON(!pte_none(pte)); > > +} > > + > > +static void __init pmd_clear_tests(struct mm_struct *mm, pmd_t *pmdp= ) > > +{ > > + pmd_t pmd =3D READ_ONCE(*pmdp); > > + > > + pmd =3D __pmd(pmd_val(pmd) | RANDOM_ORVALUE); > > + WRITE_ONCE(*pmdp, pmd); > > + pmd_clear(pmdp); > > + pmd =3D READ_ONCE(*pmdp); > > + WARN_ON(!pmd_none(pmd)); > > +} > > + > > +static void __init pmd_populate_tests(struct mm_struct *mm, pmd_t *p= mdp, > > + pgtable_t pgtable) > > +{ > > + pmd_t pmd; > > + > > + /* > > + * This entry points to next level page table page. > > + * Hence this must not qualify as pmd_bad(). > > + */ > > + pmd_clear(pmdp); > > + pmd_populate(mm, pmdp, pgtable); > > + pmd =3D READ_ONCE(*pmdp); > > + WARN_ON(pmd_bad(pmd)); > > +} > > + > > +static unsigned long __init get_random_vaddr(void) > > +{ > > + unsigned long random_vaddr, random_pages, total_user_pages; > > + > > + total_user_pages =3D (TASK_SIZE - FIRST_USER_ADDRESS) / PAGE_SIZE; > > + > > + random_pages =3D get_random_long() % total_user_pages; > > + random_vaddr =3D FIRST_USER_ADDRESS + random_pages * PAGE_SIZE; > > + > > + return random_vaddr; > > +} > > + > > +void __init debug_vm_pgtable(void) > > +{ > > + struct mm_struct *mm; > > + pgd_t *pgdp; > > + p4d_t *p4dp, *saved_p4dp; > > + pud_t *pudp, *saved_pudp; > > + pmd_t *pmdp, *saved_pmdp, pmd; > > + pte_t *ptep; > > + pgtable_t saved_ptep; > > + pgprot_t prot; > > + phys_addr_t paddr; > > + unsigned long vaddr, pte_aligned, pmd_aligned; > > + unsigned long pud_aligned, p4d_aligned, pgd_aligned; > > + > > + pr_info("Validating architecture page table helpers\n"); > > + prot =3D vm_get_page_prot(VMFLAGS); > > + vaddr =3D get_random_vaddr(); > > + mm =3D mm_alloc(); > > + if (!mm) { > > + pr_err("mm_struct allocation failed\n"); > > + return; > > + } > > + > > + /* > > + * PFN for mapping at PTE level is determined from a standard kerne= l > > + * text symbol. But pfns for higher page table levels are derived b= y > > + * masking lower bits of this real pfn. These derived pfns might no= t > > + * exist on the platform but that does not really matter as pfn_pxx= () > > + * helpers will still create appropriate entries for the test. This > > + * helps avoid large memory block allocations to be used for mappin= g > > + * at higher page table levels. > > + */ > > + paddr =3D __pa(&start_kernel); > > + > > + pte_aligned =3D (paddr & PAGE_MASK) >> PAGE_SHIFT; > > + pmd_aligned =3D (paddr & PMD_MASK) >> PAGE_SHIFT; > > + pud_aligned =3D (paddr & PUD_MASK) >> PAGE_SHIFT; > > + p4d_aligned =3D (paddr & P4D_MASK) >> PAGE_SHIFT; > > + pgd_aligned =3D (paddr & PGDIR_MASK) >> PAGE_SHIFT; > > + WARN_ON(!pfn_valid(pte_aligned)); > > + > > + pgdp =3D pgd_offset(mm, vaddr); > > + p4dp =3D p4d_alloc(mm, pgdp, vaddr); > > + pudp =3D pud_alloc(mm, p4dp, vaddr); > > + pmdp =3D pmd_alloc(mm, pudp, vaddr); > > + ptep =3D pte_alloc_map(mm, pmdp, vaddr); > > + > > + /* > > + * Save all the page table page addresses as the page table > > + * entries will be used for testing with random or garbage > > + * values. These saved addresses will be used for freeing > > + * page table pages. > > + */ > > + pmd =3D READ_ONCE(*pmdp); > > + saved_p4dp =3D p4d_offset(pgdp, 0UL); > > + saved_pudp =3D pud_offset(p4dp, 0UL); > > + saved_pmdp =3D pmd_offset(pudp, 0UL); > > + saved_ptep =3D pmd_pgtable(pmd); > > + > > + pte_basic_tests(pte_aligned, prot); > > + pmd_basic_tests(pmd_aligned, prot); > > + pud_basic_tests(pud_aligned, prot); > > + p4d_basic_tests(p4d_aligned, prot); > > + pgd_basic_tests(pgd_aligned, prot); > > + > > + pte_clear_tests(mm, ptep); > > + pmd_clear_tests(mm, pmdp); > > + pud_clear_tests(mm, pudp); > > + p4d_clear_tests(mm, p4dp); > > + pgd_clear_tests(mm, pgdp); > > + > > + pte_unmap(ptep); > > + > > + pmd_populate_tests(mm, pmdp, saved_ptep); > > + pud_populate_tests(mm, pudp, saved_pmdp); > > + p4d_populate_tests(mm, p4dp, saved_pudp); > > + pgd_populate_tests(mm, pgdp, saved_p4dp); > > + > > + p4d_free(mm, saved_p4dp); > > + pud_free(mm, saved_pudp); > > + pmd_free(mm, saved_pmdp); > > + pte_free(mm, saved_ptep); > > + > > + mm_dec_nr_puds(mm); > > + mm_dec_nr_pmds(mm); > > + mm_dec_nr_ptes(mm); > > + mmdrop(mm); > > +}