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.2 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED,USER_AGENT_SANE_1 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 487B2CA9EAF for ; Thu, 24 Oct 2019 18:15:43 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id B941C20663 for ; Thu, 24 Oct 2019 18:15:42 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B941C20663 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 2DF7A6B0007; Thu, 24 Oct 2019 14:15:42 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 290526B0008; Thu, 24 Oct 2019 14:15:42 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 158976B000A; Thu, 24 Oct 2019 14:15:42 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0075.hostedemail.com [216.40.44.75]) by kanga.kvack.org (Postfix) with ESMTP id D8AF26B0007 for ; Thu, 24 Oct 2019 14:15:41 -0400 (EDT) Received: from smtpin29.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay01.hostedemail.com (Postfix) with SMTP id 86E70181AEF21 for ; Thu, 24 Oct 2019 18:15:41 +0000 (UTC) X-FDA: 76079481282.29.time91_88dbe99ed835e X-HE-Tag: time91_88dbe99ed835e X-Filterd-Recvd-Size: 30850 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by imf45.hostedemail.com (Postfix) with ESMTP for ; Thu, 24 Oct 2019 18:15:40 +0000 (UTC) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id D56B51000; Tue, 22 Oct 2019 04:18:21 -0700 (PDT) Received: from [10.162.40.145] (p8cg001049571a15.blr.arm.com [10.162.40.145]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 5A0F93F718; Tue, 22 Oct 2019 04:18:09 -0700 (PDT) Subject: Re: [PATCH V7] mm/debug: Add tests validating architecture page table helpers To: Christophe Leroy , linux-mm@kvack.org Cc: Andrew Morton , Vlastimil Babka , Greg Kroah-Hartman , Thomas Gleixner , Mike Rapoport , Jason Gunthorpe , Dan Williams , Peter Zijlstra , Michal Hocko , Mark Rutland , Mark Brown , Steven Price , Ard Biesheuvel , Masahiro Yamada , Kees Cook , Tetsuo Handa , Matthew Wilcox , Sri Krishna chowdary , Dave Hansen , Russell King - ARM Linux , Michael Ellerman , Paul Mackerras , Martin Schwidefsky , Heiko Carstens , "David S. Miller" , Vineet Gupta , James Hogan , Paul Burton , Ralf Baechle , "Kirill A . Shutemov" , Gerald Schaefer , Ingo Molnar , linux-snps-arc@lists.infradead.org, linux-mips@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-ia64@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-s390@vger.kernel.org, linux-sh@vger.kernel.org, sparclinux@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org References: <1571625739-29943-1-git-send-email-anshuman.khandual@arm.com> <1571625739-29943-2-git-send-email-anshuman.khandual@arm.com> <535564eb-65ea-69ab-977d-0038a9e4f785@c-s.fr> From: Anshuman Khandual Message-ID: Date: Tue, 22 Oct 2019 16:48:38 +0530 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.9.1 MIME-Version: 1.0 In-Reply-To: <535564eb-65ea-69ab-977d-0038a9e4f785@c-s.fr> Content-Type: text/plain; charset=utf-8 Content-Language: en-US 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 10/22/2019 12:41 PM, Christophe Leroy wrote: >=20 >=20 > On 10/21/2019 02:42 AM, Anshuman Khandual wrote: >> This adds tests which will validate architecture page table helpers an= d >> other accessors in their compliance with expected generic MM semantics= . >> This will help various architectures in validating changes to existing >> page table helpers or addition of new ones. >> >> This test covers basic page table entry transformations including but = not >> limited to old, young, dirty, clean, write, write protect etc at vario= us >> level along with populating intermediate entries with next page table = page >> and validating them. >> >> Test page table pages are allocated from system memory with required s= ize >> and alignments. The mapped pfns at page table levels are derived from = a >> real pfn representing a valid kernel text symbol. This test gets calle= d >> right after page_alloc_init_late(). >> >> This gets build and run when CONFIG_DEBUG_VM_PGTABLE is selected along= with >> CONFIG_VM_DEBUG. Architectures willing to subscribe this test also nee= d to >> select CONFIG_ARCH_HAS_DEBUG_VM_PGTABLE which for now is limited to x8= 6 and >> arm64. Going forward, other architectures too can enable this after fi= xing >> build or runtime problems (if any) with their page table helpers. >> >> Folks interested in making sure that a given platform's page table hel= pers >> conform to expected generic MM semantics should enable the above confi= g >> which will just trigger this test during boot. Any non conformity here= will >> be reported as an warning which would need to be fixed. This test will= help >> catch any changes to the agreed upon semantics expected from generic M= M and >> enable platforms to accommodate it thereafter. >> >> Cc: Andrew Morton >> Cc: Vlastimil Babka >> Cc: Greg Kroah-Hartman >> Cc: Thomas Gleixner >> Cc: Mike Rapoport >> Cc: Jason Gunthorpe >> Cc: Dan Williams >> Cc: Peter Zijlstra >> Cc: Michal Hocko >> Cc: Mark Rutland >> Cc: Mark Brown >> Cc: Steven Price >> Cc: Ard Biesheuvel >> Cc: Masahiro Yamada >> Cc: Kees Cook >> Cc: Tetsuo Handa >> Cc: Matthew Wilcox >> Cc: Sri Krishna chowdary >> Cc: Dave Hansen >> Cc: Russell King - ARM Linux >> Cc: Michael Ellerman >> Cc: Paul Mackerras >> Cc: Martin Schwidefsky >> Cc: Heiko Carstens >> Cc: "David S. Miller" >> Cc: Vineet Gupta >> Cc: James Hogan >> Cc: Paul Burton >> Cc: Ralf Baechle >> Cc: Kirill A. Shutemov >> Cc: Gerald Schaefer >> Cc: Christophe Leroy >> Cc: Ingo Molnar >> Cc: linux-snps-arc@lists.infradead.org >> Cc: linux-mips@vger.kernel.org >> Cc: linux-arm-kernel@lists.infradead.org >> Cc: linux-ia64@vger.kernel.org >> Cc: linuxppc-dev@lists.ozlabs.org >> Cc: linux-s390@vger.kernel.org >> Cc: linux-sh@vger.kernel.org >> Cc: sparclinux@vger.kernel.org >> Cc: x86@kernel.org >> Cc: linux-kernel@vger.kernel.org >> >> Tested-by: Christophe Leroy =C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0 #PPC32 >> Suggested-by: Catalin Marinas >> Signed-off-by: Andrew Morton >> Signed-off-by: Christophe Leroy >> Signed-off-by: Anshuman Khandual >> --- >=20 > The cover letter have the exact same title as this patch. I think a cov= er letter is not necessary for a singleton series. Right, but it became singleton series in this version :) >=20 > The history (and any other information you don't want to include in the= commit message) can be added here, below the '---'. That way it is in th= e mail but won't be included in the commit. I was aware about that but the change log here was big, hence just choose= to have that separately in a cover letter. As you said, I guess the cover letter is pr= obably not required anymore. Will add it here in the patch, next time around. >=20 >> =C2=A0 .../debug/debug-vm-pgtable/arch-support.txt=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0 |=C2=A0 34 ++ >> =C2=A0 arch/arm64/Kconfig=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=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=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 = |=C2=A0=C2=A0 1 + >> =C2=A0 arch/x86/Kconfig=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=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=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0 |=C2=A0=C2=A0 1 + >> =C2=A0 arch/x86/include/asm/pgtable_64.h=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=C2=A0=C2=A0=C2=A0=C2=A0 = |=C2=A0=C2=A0 6 + >> =C2=A0 include/asm-generic/pgtable.h=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=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0 |=C2=A0=C2=A0 6 + >> =C2=A0 init/main.c=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=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=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 |=C2=A0=C2=A0 1 + >> =C2=A0 lib/Kconfig.debug=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=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=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= |=C2=A0 21 ++ >> =C2=A0 mm/Makefile=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=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=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 |=C2=A0=C2=A0 1 + >> =C2=A0 mm/debug_vm_pgtable.c=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=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=C2=A0=C2=A0=C2=A0 | 388 +++++++++= ++++++++++++ >> =C2=A0 9 files changed, 459 insertions(+) >> =C2=A0 create mode 100644 Documentation/features/debug/debug-vm-pgtabl= e/arch-support.txt >> =C2=A0 create mode 100644 mm/debug_vm_pgtable.c >> >> diff --git a/Documentation/features/debug/debug-vm-pgtable/arch-suppor= t.txt b/Documentation/features/debug/debug-vm-pgtable/arch-support.txt >> new file mode 100644 >> index 0000000..d6b8185 >> --- /dev/null >> +++ b/Documentation/features/debug/debug-vm-pgtable/arch-support.txt >> @@ -0,0 +1,34 @@ >> +# >> +# Feature name:=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= debug-vm-pgtable >> +#=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 Kconfig:=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0 ARCH_HAS_DEBUG_VM_PGTABLE >> +#=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 description:=C2=A0=C2= =A0 arch supports pgtable tests for semantics compliance >> +# >> +=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=C2=A0 = arch |status| >> +=C2=A0=C2=A0=C2=A0 ----------------------- >> +=C2=A0=C2=A0=C2=A0 |=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 alpha: | TOD= O | >> +=C2=A0=C2=A0=C2=A0 |=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 = arc: | TODO | >> +=C2=A0=C2=A0=C2=A0 |=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 = arm: | TODO | >> +=C2=A0=C2=A0=C2=A0 |=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 arm64: |=C2=A0= ok=C2=A0 | >> +=C2=A0=C2=A0=C2=A0 |=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 = c6x: | TODO | >> +=C2=A0=C2=A0=C2=A0 |=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 csky: = | TODO | >> +=C2=A0=C2=A0=C2=A0 |=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 h8300: | TOD= O | >> +=C2=A0=C2=A0=C2=A0 |=C2=A0=C2=A0=C2=A0=C2=A0 hexagon: | TODO | >> +=C2=A0=C2=A0=C2=A0 |=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ia64: = | TODO | >> +=C2=A0=C2=A0=C2=A0 |=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 m68k: = | TODO | >> +=C2=A0=C2=A0=C2=A0 |=C2=A0 microblaze: | TODO | >> +=C2=A0=C2=A0=C2=A0 |=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 mips: = | TODO | >> +=C2=A0=C2=A0=C2=A0 |=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 nds32: | TOD= O | >> +=C2=A0=C2=A0=C2=A0 |=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 nios2: | TOD= O | >> +=C2=A0=C2=A0=C2=A0 |=C2=A0=C2=A0=C2=A0 openrisc: | TODO | >> +=C2=A0=C2=A0=C2=A0 |=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 parisc: | TODO | >> +=C2=A0=C2=A0=C2=A0 |=C2=A0=C2=A0=C2=A0=C2=A0 powerpc: | TODO | >=20 > Say ok on ppc32 Will do. >=20 >> +=C2=A0=C2=A0=C2=A0 |=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 riscv: | TOD= O | >> +=C2=A0=C2=A0=C2=A0 |=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 s390: = | TODO | >> +=C2=A0=C2=A0=C2=A0 |=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0 sh: | TODO | >> +=C2=A0=C2=A0=C2=A0 |=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 sparc: | TOD= O | >> +=C2=A0=C2=A0=C2=A0 |=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0 um: | TODO | >> +=C2=A0=C2=A0=C2=A0 |=C2=A0=C2=A0 unicore32: | TODO | >> +=C2=A0=C2=A0=C2=A0 |=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 = x86: |=C2=A0 ok=C2=A0 | >> +=C2=A0=C2=A0=C2=A0 |=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 xtensa: | TODO | >> +=C2=A0=C2=A0=C2=A0 ----------------------- >> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig >> index 1b6ea5a..ea62c87 100644 >> --- a/arch/arm64/Kconfig >> +++ b/arch/arm64/Kconfig >> @@ -11,6 +11,7 @@ config ARM64 >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 select ACPI_PPTT if ACPI >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 select ARCH_CLOCKSOURCE_DATA >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 select ARCH_HAS_DEBUG_VIRTUAL >> +=C2=A0=C2=A0=C2=A0 select ARCH_HAS_DEBUG_VM_PGTABLE >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 select ARCH_HAS_DEVMEM_IS_ALLOWED >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 select ARCH_HAS_DMA_COHERENT_TO_PFN >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 select ARCH_HAS_DMA_PREP_COHERENT >> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig >> index abe822d..13c9bd9 100644 >> --- a/arch/x86/Kconfig >> +++ b/arch/x86/Kconfig >> @@ -61,6 +61,7 @@ config X86 >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 select ARCH_CLOCKSOURCE_INIT >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 select ARCH_HAS_ACPI_TABLE_UPGRADE=C2=A0= =C2=A0=C2=A0 if ACPI >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 select ARCH_HAS_DEBUG_VIRTUAL >> +=C2=A0=C2=A0=C2=A0 select ARCH_HAS_DEBUG_VM_PGTABLE >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 select ARCH_HAS_DEVMEM_IS_ALLOWED >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 select ARCH_HAS_ELF_RANDOMIZE >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 select ARCH_HAS_FAST_MULTIPLIER >=20 > diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig > index 3e56c9c2f16e..c50d7cfa566b 100644 > --- a/arch/powerpc/Kconfig > +++ b/arch/powerpc/Kconfig > @@ -120,6 +120,7 @@ config PPC > =C2=A0=C2=A0=C2=A0=C2=A0 # > =C2=A0=C2=A0=C2=A0=C2=A0 select ARCH_32BIT_OFF_T if PPC32 > =C2=A0=C2=A0=C2=A0=C2=A0 select ARCH_HAS_DEBUG_VIRTUAL > +=C2=A0=C2=A0=C2=A0 select ARCH_HAS_DEBUG_VM_PGTABLE if PPC32 > =C2=A0=C2=A0=C2=A0=C2=A0 select ARCH_HAS_DEVMEM_IS_ALLOWED > =C2=A0=C2=A0=C2=A0=C2=A0 select ARCH_HAS_ELF_RANDOMIZE > =C2=A0=C2=A0=C2=A0=C2=A0 select ARCH_HAS_FORTIFY_SOURCE >=20 >=20 Will add this. >> diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/= pgtable_64.h >> index 0b6c4042..fb0e76d 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) { = } >> =C2=A0 =C2=A0 struct mm_struct; >> =C2=A0 +#define mm_p4d_folded mm_p4d_folded >> +static inline bool mm_p4d_folded(struct mm_struct *mm) >> +{ >> +=C2=A0=C2=A0=C2=A0 return !pgtable_l5_enabled(); >> +} >> + >> =C2=A0 void set_pte_vaddr_p4d(p4d_t *p4d_page, unsigned long vaddr, pt= e_t new_pte); >> =C2=A0 void set_pte_vaddr_pud(pud_t *pud_page, unsigned long vaddr, pt= e_t new_pte); >> =C2=A0 diff --git a/include/asm-generic/pgtable.h b/include/asm-generi= c/pgtable.h >> index 9cdcbc7..9eb02e1 100644 >> --- a/include/asm-generic/pgtable.h >> +++ b/include/asm-generic/pgtable.h >> @@ -1168,6 +1168,12 @@ static inline bool arch_has_pfn_modify_check(vo= id) >> =C2=A0 # define PAGE_KERNEL_EXEC PAGE_KERNEL >> =C2=A0 #endif >> =C2=A0 +#ifdef CONFIG_DEBUG_VM_PGTABLE >> +extern void debug_vm_pgtable(void); >> +#else >> +static inline void debug_vm_pgtable(void) { } >> +#endif >> + >> =C2=A0 #endif /* !__ASSEMBLY__ */ >> =C2=A0 =C2=A0 #ifndef io_remap_pfn_range >> diff --git a/init/main.c b/init/main.c >> index 91f6ebb..af8379e 100644 >> --- a/init/main.c >> +++ b/init/main.c >> @@ -1185,6 +1185,7 @@ static noinline void __init kernel_init_freeable= (void) >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 sched_init_smp(); >> =C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 page_alloc_init_late(); >> +=C2=A0=C2=A0=C2=A0 debug_vm_pgtable(); >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /* Initialize page ext after all struct= pages are initialized. */ >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 page_ext_init(); >> =C2=A0 diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug >> index 9c60d7d..cf48d95 100644 >> --- a/lib/Kconfig.debug >> +++ b/lib/Kconfig.debug >> @@ -690,6 +690,27 @@ config DEBUG_VM_PGFLAGS >> =C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 If unsure, say N. >> =C2=A0 +config ARCH_HAS_DEBUG_VM_PGTABLE >> +=C2=A0=C2=A0=C2=A0 bool >> +=C2=A0=C2=A0=C2=A0 help >> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 An architecture should select this whe= n it can successfully >> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 build and run DEBUG_VM_PGTABLE. >> + >> +config DEBUG_VM_PGTABLE >> +=C2=A0=C2=A0=C2=A0 bool "Debug arch page table for semantics complian= ce" >> +=C2=A0=C2=A0=C2=A0 depends on MMU >> +=C2=A0=C2=A0=C2=A0 depends on DEBUG_VM >> +=C2=A0=C2=A0=C2=A0 depends on ARCH_HAS_DEBUG_VM_PGTABLE >> +=C2=A0=C2=A0=C2=A0 help >> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 This option provides a debug method wh= ich can be used to test >> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 architecture page table helper functio= ns on various platforms in >> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 verifying if they comply with expected= generic MM semantics. This >> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 will help architecture code in making = sure that any changes or >> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 new additions of these helpers still c= onform to expected >> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 semantics of the generic MM. >> + >> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 If unsure, say N. >> + >=20 > Would be nice to have that one also indented like the other DEBUG_VM_XX= XXX (see below). >=20 > Stack utilization instrumentation (DEBUG_STACK_USAGE) [N/y/?] n > Debug VM (DEBUG_VM) [N/y/?] (NEW) y > =C2=A0 Debug VMA caching (DEBUG_VM_VMACACHE) [N/y/?] (NEW) > =C2=A0 Debug VM red-black trees (DEBUG_VM_RB) [N/y/?] (NEW) > =C2=A0 Debug page-flags operations (DEBUG_VM_PGFLAGS) [N/y/?] (NEW) > Debug arch page table for semantics compliance (DEBUG_VM_PGTABLE) [N/y/= ?] (NEW) > Debug VM translations (DEBUG_VIRTUAL) [N/y/?] n >=20 >=20 > For that, just move config ARCH_HAS_DEBUG_VM_PGTABLE somewhere else, ma= ybe before DEBUG_VM or just after DEBUG_VM_PGTABLE Initially I had ARCH_HAS_DEBUG_VM_PGTABLE after DEBUG_VM_PGTABLE but reve= rsed that because of it's dependency. So will probably move it before DEBUG_VM= . >=20 >=20 >> =C2=A0 config ARCH_HAS_DEBUG_VIRTUAL >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 bool >> =C2=A0 diff --git a/mm/Makefile b/mm/Makefile >> index d996846..2f085b9 100644 >> --- a/mm/Makefile >> +++ b/mm/Makefile >> @@ -86,6 +86,7 @@ obj-$(CONFIG_HWPOISON_INJECT) +=3D hwpoison-inject.o >> =C2=A0 obj-$(CONFIG_DEBUG_KMEMLEAK) +=3D kmemleak.o >> =C2=A0 obj-$(CONFIG_DEBUG_KMEMLEAK_TEST) +=3D kmemleak-test.o >> =C2=A0 obj-$(CONFIG_DEBUG_RODATA_TEST) +=3D rodata_test.o >> +obj-$(CONFIG_DEBUG_VM_PGTABLE) +=3D debug_vm_pgtable.o >> =C2=A0 obj-$(CONFIG_PAGE_OWNER) +=3D page_owner.o >> =C2=A0 obj-$(CONFIG_CLEANCACHE) +=3D cleancache.o >> =C2=A0 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 0000000..9472566 >> --- /dev/null >> +++ b/mm/debug_vm_pgtable.c >> @@ -0,0 +1,388 @@ >> +// 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) "arch_pgtable_test: %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)=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0 =3D An old and not a young entry >> + * mkyoung(entry)=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 =3D A you= ng and not an old entry >> + * mkdirty(entry)=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 =3D A dir= ty and not a clean entry >> + * mkclean(entry)=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 =3D A cle= an and not a dirty entry >> + * mkwrite(entry)=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 =3D A wri= te and not a write protected entry >> + * wrprotect(entry)=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 =3D A w= rite protected and not a write entry >> + * pxx_bad(entry)=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 =3D A map= ped and non-table entry >> + * pxx_same(entry1, entry2)=C2=A0=C2=A0=C2=A0 =3D Both entries hold t= he exact same value >> + */ >> +#define VMFLAGS=C2=A0=C2=A0=C2=A0 (VM_READ|VM_WRITE|VM_EXEC) >> + >> +/* >> + * On s390 platform, the lower 12 bits are used to identify given pag= e table >> + * entry type and for other arch specific requirements. But these bit= s might >> + * affect the ability to clear entries with pxx_clear(). So while loa= ding up >> + * the entries skip all lower 12 bits in order to accommodate s390 pl= atform. >> + * It does not have affect any other platform. >> + */ >> +#define RANDOM_ORVALUE=C2=A0=C2=A0=C2=A0 (0xfffffffffffff000UL) >> +#define RANDOM_NZVALUE=C2=A0=C2=A0=C2=A0 (0xff) >> + >> +static void __init pte_basic_tests(unsigned long pfn, pgprot_t prot) >> +{ >> +=C2=A0=C2=A0=C2=A0 pte_t pte =3D pfn_pte(pfn, prot); >> + >> +=C2=A0=C2=A0=C2=A0 WARN_ON(!pte_same(pte, pte)); >> +=C2=A0=C2=A0=C2=A0 WARN_ON(!pte_young(pte_mkyoung(pte))); >> +=C2=A0=C2=A0=C2=A0 WARN_ON(!pte_dirty(pte_mkdirty(pte))); >> +=C2=A0=C2=A0=C2=A0 WARN_ON(!pte_write(pte_mkwrite(pte))); >> +=C2=A0=C2=A0=C2=A0 WARN_ON(pte_young(pte_mkold(pte))); >> +=C2=A0=C2=A0=C2=A0 WARN_ON(pte_dirty(pte_mkclean(pte))); >> +=C2=A0=C2=A0=C2=A0 WARN_ON(pte_write(pte_wrprotect(pte))); >> +} >> + >> +#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE >> +static void __init pmd_basic_tests(unsigned long pfn, pgprot_t prot) >> +{ >> +=C2=A0=C2=A0=C2=A0 pmd_t pmd =3D pfn_pmd(pfn, prot); >> + >> +=C2=A0=C2=A0=C2=A0 WARN_ON(!pmd_same(pmd, pmd)); >> +=C2=A0=C2=A0=C2=A0 WARN_ON(!pmd_young(pmd_mkyoung(pmd))); >> +=C2=A0=C2=A0=C2=A0 WARN_ON(!pmd_dirty(pmd_mkdirty(pmd))); >> +=C2=A0=C2=A0=C2=A0 WARN_ON(!pmd_write(pmd_mkwrite(pmd))); >> +=C2=A0=C2=A0=C2=A0 WARN_ON(pmd_young(pmd_mkold(pmd))); >> +=C2=A0=C2=A0=C2=A0 WARN_ON(pmd_dirty(pmd_mkclean(pmd))); >> +=C2=A0=C2=A0=C2=A0 WARN_ON(pmd_write(pmd_wrprotect(pmd))); >> +=C2=A0=C2=A0=C2=A0 /* >> +=C2=A0=C2=A0=C2=A0=C2=A0 * A huge page does not point to next level p= age table >> +=C2=A0=C2=A0=C2=A0=C2=A0 * entry. Hence this must qualify as pmd_bad(= ). >> +=C2=A0=C2=A0=C2=A0=C2=A0 */ >> +=C2=A0=C2=A0=C2=A0 WARN_ON(!pmd_bad(pmd_mkhuge(pmd))); >> +} >> +#else >> +static void __init pmd_basic_tests(unsigned long pfn, pgprot_t prot) = { } >> +#endif >> + >> +#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD >> +static void __init pud_basic_tests(unsigned long pfn, pgprot_t prot) >> +{ >> +=C2=A0=C2=A0=C2=A0 pud_t pud =3D pfn_pud(pfn, prot); >> + >> +=C2=A0=C2=A0=C2=A0 WARN_ON(!pud_same(pud, pud)); >> +=C2=A0=C2=A0=C2=A0 WARN_ON(!pud_young(pud_mkyoung(pud))); >> +=C2=A0=C2=A0=C2=A0 WARN_ON(!pud_write(pud_mkwrite(pud))); >> +=C2=A0=C2=A0=C2=A0 WARN_ON(pud_write(pud_wrprotect(pud))); >> +=C2=A0=C2=A0=C2=A0 WARN_ON(pud_young(pud_mkold(pud))); >> + >> +=C2=A0=C2=A0=C2=A0 if (mm_pmd_folded(mm) || __is_defined(ARCH_HAS_4LE= VEL_HACK)) >> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return; >> + >> +=C2=A0=C2=A0=C2=A0 /* >> +=C2=A0=C2=A0=C2=A0=C2=A0 * A huge page does not point to next level p= age table >> +=C2=A0=C2=A0=C2=A0=C2=A0 * entry. Hence this must qualify as pud_bad(= ). >> +=C2=A0=C2=A0=C2=A0=C2=A0 */ >> +=C2=A0=C2=A0=C2=A0 WARN_ON(!pud_bad(pud_mkhuge(pud))); >> +} >> +#else >> +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) >> +{ >> +=C2=A0=C2=A0=C2=A0 p4d_t p4d; >> + >> +=C2=A0=C2=A0=C2=A0 memset(&p4d, RANDOM_NZVALUE, sizeof(p4d_t)); >> +=C2=A0=C2=A0=C2=A0 WARN_ON(!p4d_same(p4d, p4d)); >> +} >> + >> +static void __init pgd_basic_tests(unsigned long pfn, pgprot_t prot) >> +{ >> +=C2=A0=C2=A0=C2=A0 pgd_t pgd; >> + >> +=C2=A0=C2=A0=C2=A0 memset(&pgd, RANDOM_NZVALUE, sizeof(pgd_t)); >> +=C2=A0=C2=A0=C2=A0 WARN_ON(!pgd_same(pgd, pgd)); >> +} >> + >> +#ifndef __ARCH_HAS_4LEVEL_HACK >> +static void __init pud_clear_tests(struct mm_struct *mm, pud_t *pudp) >> +{ >> +=C2=A0=C2=A0=C2=A0 pud_t pud =3D READ_ONCE(*pudp); >> + >> +=C2=A0=C2=A0=C2=A0 if (mm_pmd_folded(mm)) >> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return; >> + >> +=C2=A0=C2=A0=C2=A0 pud =3D __pud(pud_val(pud) | RANDOM_ORVALUE); >> +=C2=A0=C2=A0=C2=A0 WRITE_ONCE(*pudp, pud); >> +=C2=A0=C2=A0=C2=A0 pud_clear(pudp); >> +=C2=A0=C2=A0=C2=A0 pud =3D READ_ONCE(*pudp); >> +=C2=A0=C2=A0=C2=A0 WARN_ON(!pud_none(pud)); >> +} >> + >> +static void __init pud_populate_tests(struct mm_struct *mm, pud_t *pu= dp, >> +=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=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 pmd_t *pmdp) >> +{ >> +=C2=A0=C2=A0=C2=A0 pud_t pud; >> + >> +=C2=A0=C2=A0=C2=A0 if (mm_pmd_folded(mm)) >> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return; >> +=C2=A0=C2=A0=C2=A0 /* >> +=C2=A0=C2=A0=C2=A0=C2=A0 * This entry points to next level page table= page. >> +=C2=A0=C2=A0=C2=A0=C2=A0 * Hence this must not qualify as pud_bad(). >> +=C2=A0=C2=A0=C2=A0=C2=A0 */ >> +=C2=A0=C2=A0=C2=A0 pmd_clear(pmdp); >> +=C2=A0=C2=A0=C2=A0 pud_clear(pudp); >> +=C2=A0=C2=A0=C2=A0 pud_populate(mm, pudp, pmdp); >> +=C2=A0=C2=A0=C2=A0 pud =3D READ_ONCE(*pudp); >> +=C2=A0=C2=A0=C2=A0 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 *pu= dp, >> +=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=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 pmd_t *pmdp) >> +{ >> +} >> +#endif >> + >> +#ifndef __ARCH_HAS_5LEVEL_HACK >> +static void __init p4d_clear_tests(struct mm_struct *mm, p4d_t *p4dp) >> +{ >> +=C2=A0=C2=A0=C2=A0 p4d_t p4d =3D READ_ONCE(*p4dp); >> + >> +=C2=A0=C2=A0=C2=A0 if (mm_pud_folded(mm)) >> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return; >> + >> +=C2=A0=C2=A0=C2=A0 p4d =3D __p4d(p4d_val(p4d) | RANDOM_ORVALUE); >> +=C2=A0=C2=A0=C2=A0 WRITE_ONCE(*p4dp, p4d); >> +=C2=A0=C2=A0=C2=A0 p4d_clear(p4dp); >> +=C2=A0=C2=A0=C2=A0 p4d =3D READ_ONCE(*p4dp); >> +=C2=A0=C2=A0=C2=A0 WARN_ON(!p4d_none(p4d)); >> +} >> + >> +static void __init p4d_populate_tests(struct mm_struct *mm, p4d_t *p4= dp, >> +=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=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 pud_t *pudp) >> +{ >> +=C2=A0=C2=A0=C2=A0 p4d_t p4d; >> + >> +=C2=A0=C2=A0=C2=A0 if (mm_pud_folded(mm)) >> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return; >> + >> +=C2=A0=C2=A0=C2=A0 /* >> +=C2=A0=C2=A0=C2=A0=C2=A0 * This entry points to next level page table= page. >> +=C2=A0=C2=A0=C2=A0=C2=A0 * Hence this must not qualify as p4d_bad(). >> +=C2=A0=C2=A0=C2=A0=C2=A0 */ >> +=C2=A0=C2=A0=C2=A0 pud_clear(pudp); >> +=C2=A0=C2=A0=C2=A0 p4d_clear(p4dp); >> +=C2=A0=C2=A0=C2=A0 p4d_populate(mm, p4dp, pudp); >> +=C2=A0=C2=A0=C2=A0 p4d =3D READ_ONCE(*p4dp); >> +=C2=A0=C2=A0=C2=A0 WARN_ON(p4d_bad(p4d)); >> +} >> + >> +static void __init pgd_clear_tests(struct mm_struct *mm, pgd_t *pgdp) >> +{ >> +=C2=A0=C2=A0=C2=A0 pgd_t pgd =3D READ_ONCE(*pgdp); >> + >> +=C2=A0=C2=A0=C2=A0 if (mm_p4d_folded(mm)) >> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return; >> + >> +=C2=A0=C2=A0=C2=A0 pgd =3D __pgd(pgd_val(pgd) | RANDOM_ORVALUE); >> +=C2=A0=C2=A0=C2=A0 WRITE_ONCE(*pgdp, pgd); >> +=C2=A0=C2=A0=C2=A0 pgd_clear(pgdp); >> +=C2=A0=C2=A0=C2=A0 pgd =3D READ_ONCE(*pgdp); >> +=C2=A0=C2=A0=C2=A0 WARN_ON(!pgd_none(pgd)); >> +} >> + >> +static void __init pgd_populate_tests(struct mm_struct *mm, pgd_t *pg= dp, >> +=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=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 p4d_t *p4dp) >> +{ >> +=C2=A0=C2=A0=C2=A0 pgd_t pgd; >> + >> +=C2=A0=C2=A0=C2=A0 if (mm_p4d_folded(mm)) >> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return; >> + >> +=C2=A0=C2=A0=C2=A0 /* >> +=C2=A0=C2=A0=C2=A0=C2=A0 * This entry points to next level page table= page. >> +=C2=A0=C2=A0=C2=A0=C2=A0 * Hence this must not qualify as pgd_bad(). >> +=C2=A0=C2=A0=C2=A0=C2=A0 */ >> +=C2=A0=C2=A0=C2=A0 p4d_clear(p4dp); >> +=C2=A0=C2=A0=C2=A0 pgd_clear(pgdp); >> +=C2=A0=C2=A0=C2=A0 pgd_populate(mm, pgdp, p4dp); >> +=C2=A0=C2=A0=C2=A0 pgd =3D READ_ONCE(*pgdp); >> +=C2=A0=C2=A0=C2=A0 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 *p4= dp, >> +=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=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 pud_t *pudp) >> +{ >> +} >> +static void __init pgd_populate_tests(struct mm_struct *mm, pgd_t *pg= dp, >> +=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=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 p4d_t *p4dp) >> +{ >> +} >> +#endif >> + >> +static void __init pte_clear_tests(struct mm_struct *mm, pte_t *ptep) >> +{ >> +=C2=A0=C2=A0=C2=A0 pte_t pte =3D READ_ONCE(*ptep); >> + >> +=C2=A0=C2=A0=C2=A0 pte =3D __pte(pte_val(pte) | RANDOM_ORVALUE); >> +=C2=A0=C2=A0=C2=A0 WRITE_ONCE(*ptep, pte); >> +=C2=A0=C2=A0=C2=A0 pte_clear(mm, 0, ptep); >> +=C2=A0=C2=A0=C2=A0 pte =3D READ_ONCE(*ptep); >> +=C2=A0=C2=A0=C2=A0 WARN_ON(!pte_none(pte)); >> +} >> + >> +static void __init pmd_clear_tests(struct mm_struct *mm, pmd_t *pmdp) >> +{ >> +=C2=A0=C2=A0=C2=A0 pmd_t pmd =3D READ_ONCE(*pmdp); >> + >> +=C2=A0=C2=A0=C2=A0 pmd =3D __pmd(pmd_val(pmd) | RANDOM_ORVALUE); >> +=C2=A0=C2=A0=C2=A0 WRITE_ONCE(*pmdp, pmd); >> +=C2=A0=C2=A0=C2=A0 pmd_clear(pmdp); >> +=C2=A0=C2=A0=C2=A0 pmd =3D READ_ONCE(*pmdp); >> +=C2=A0=C2=A0=C2=A0 WARN_ON(!pmd_none(pmd)); >> +} >> + >> +static void __init pmd_populate_tests(struct mm_struct *mm, pmd_t *pm= dp, >> +=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=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 pgtable_t pgtab= le) >> +{ >> +=C2=A0=C2=A0=C2=A0 pmd_t pmd; >> + >> +=C2=A0=C2=A0=C2=A0 /* >> +=C2=A0=C2=A0=C2=A0=C2=A0 * This entry points to next level page table= page. >> +=C2=A0=C2=A0=C2=A0=C2=A0 * Hence this must not qualify as pmd_bad(). >> +=C2=A0=C2=A0=C2=A0=C2=A0 */ >> +=C2=A0=C2=A0=C2=A0 pmd_clear(pmdp); >> +=C2=A0=C2=A0=C2=A0 pmd_populate(mm, pmdp, pgtable); >> +=C2=A0=C2=A0=C2=A0 pmd =3D READ_ONCE(*pmdp); >> +=C2=A0=C2=A0=C2=A0 WARN_ON(pmd_bad(pmd)); >> +} >> + >> +static unsigned long __init get_random_vaddr(void) >> +{ >> +=C2=A0=C2=A0=C2=A0 unsigned long random_vaddr, random_pages, total_us= er_pages; >> + >> +=C2=A0=C2=A0=C2=A0 total_user_pages =3D (TASK_SIZE - FIRST_USER_ADDRE= SS) / PAGE_SIZE; >> + >> +=C2=A0=C2=A0=C2=A0 random_pages =3D get_random_long() % total_user_pa= ges; >> +=C2=A0=C2=A0=C2=A0 random_vaddr =3D FIRST_USER_ADDRESS + random_pages= * PAGE_SIZE; >> + >> +=C2=A0=C2=A0=C2=A0 WARN_ON((random_vaddr > TASK_SIZE) || >> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (random_vaddr < FIRST_USER= _ADDRESS)); >> +=C2=A0=C2=A0=C2=A0 return random_vaddr; >> +} >> + >> +void __init debug_vm_pgtable(void) >> +{ >> +=C2=A0=C2=A0=C2=A0 struct mm_struct *mm; >> +=C2=A0=C2=A0=C2=A0 pgd_t *pgdp; >> +=C2=A0=C2=A0=C2=A0 p4d_t *p4dp, *saved_p4dp; >> +=C2=A0=C2=A0=C2=A0 pud_t *pudp, *saved_pudp; >> +=C2=A0=C2=A0=C2=A0 pmd_t *pmdp, *saved_pmdp, pmd; >> +=C2=A0=C2=A0=C2=A0 pte_t *ptep; >> +=C2=A0=C2=A0=C2=A0 pgtable_t saved_ptep; >> +=C2=A0=C2=A0=C2=A0 pgprot_t prot; >> +=C2=A0=C2=A0=C2=A0 phys_addr_t paddr; >> +=C2=A0=C2=A0=C2=A0 unsigned long vaddr, pte_aligned, pmd_aligned; >> +=C2=A0=C2=A0=C2=A0 unsigned long pud_aligned, p4d_aligned, pgd_aligne= d; >=20 > I think an information message would be nice: >=20 > diff --git a/mm/debug_vm_pgtable.c b/mm/debug_vm_pgtable.c > index 9472566b7e53..ed7cc3dfc968 100644 > --- a/mm/debug_vm_pgtable.c > +++ b/mm/debug_vm_pgtable.c > @@ -313,6 +313,8 @@ void __init debug_vm_pgtable(void) > =C2=A0=C2=A0=C2=A0=C2=A0 unsigned long vaddr, pte_aligned, pmd_aligned; > =C2=A0=C2=A0=C2=A0=C2=A0 unsigned long pud_aligned, p4d_aligned, pgd_al= igned; >=20 > +=C2=A0=C2=A0=C2=A0 pr_info("Validating architecture page table helpers= \n"); > + > =C2=A0=C2=A0=C2=A0=C2=A0 prot =3D vm_get_page_prot(VMFLAGS); > =C2=A0=C2=A0=C2=A0=C2=A0 vaddr =3D get_random_vaddr(); > =C2=A0=C2=A0=C2=A0=C2=A0 mm =3D mm_alloc(); Sure, will add. Thanks ! >=20 > Christophe >=20 >> + >> +=C2=A0=C2=A0=C2=A0 prot =3D vm_get_page_prot(VMFLAGS); >> +=C2=A0=C2=A0=C2=A0 vaddr =3D get_random_vaddr(); >> +=C2=A0=C2=A0=C2=A0 mm =3D mm_alloc(); >> +=C2=A0=C2=A0=C2=A0 if (!mm) { >> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 pr_err("mm_struct allocati= on failed\n"); >> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return; >> +=C2=A0=C2=A0=C2=A0 } >> + >> +=C2=A0=C2=A0=C2=A0 /* >> +=C2=A0=C2=A0=C2=A0=C2=A0 * PFN for mapping at PTE level is determined= from a standard kernel >> +=C2=A0=C2=A0=C2=A0=C2=A0 * text symbol. But pfns for higher page tabl= e levels are derived by >> +=C2=A0=C2=A0=C2=A0=C2=A0 * masking lower bits of this real pfn. These= derived pfns might not >> +=C2=A0=C2=A0=C2=A0=C2=A0 * exist on the platform but that does not re= ally matter as pfn_pxx() >> +=C2=A0=C2=A0=C2=A0=C2=A0 * helpers will still create appropriate entr= ies for the test. This >> +=C2=A0=C2=A0=C2=A0=C2=A0 * helps avoid large memory block allocations= to be used for mapping >> +=C2=A0=C2=A0=C2=A0=C2=A0 * at higher page table levels. >> +=C2=A0=C2=A0=C2=A0=C2=A0 */ >> +=C2=A0=C2=A0=C2=A0 WARN_ON(!virt_addr_valid(&start_kernel)); >> +=C2=A0=C2=A0=C2=A0 paddr =3D __pa(&start_kernel); >> + >> +=C2=A0=C2=A0=C2=A0 pte_aligned =3D (paddr & PAGE_MASK) >> PAGE_SHIFT; >> +=C2=A0=C2=A0=C2=A0 pmd_aligned =3D (paddr & PMD_MASK) >> PAGE_SHIFT; >> +=C2=A0=C2=A0=C2=A0 pud_aligned =3D (paddr & PUD_MASK) >> PAGE_SHIFT; >> +=C2=A0=C2=A0=C2=A0 p4d_aligned =3D (paddr & P4D_MASK) >> PAGE_SHIFT; >> +=C2=A0=C2=A0=C2=A0 pgd_aligned =3D (paddr & PGDIR_MASK) >> PAGE_SHIFT= ; >> + >> +=C2=A0=C2=A0=C2=A0 pgdp =3D pgd_offset(mm, vaddr); >> +=C2=A0=C2=A0=C2=A0 p4dp =3D p4d_alloc(mm, pgdp, vaddr); >> +=C2=A0=C2=A0=C2=A0 pudp =3D pud_alloc(mm, p4dp, vaddr); >> +=C2=A0=C2=A0=C2=A0 pmdp =3D pmd_alloc(mm, pudp, vaddr); >> +=C2=A0=C2=A0=C2=A0 ptep =3D pte_alloc_map(mm, pmdp, vaddr); >> + >> +=C2=A0=C2=A0=C2=A0 /* >> +=C2=A0=C2=A0=C2=A0=C2=A0 * Save all the page table page addresses as = the page table >> +=C2=A0=C2=A0=C2=A0=C2=A0 * entries will be used for testing with rand= om or garbage >> +=C2=A0=C2=A0=C2=A0=C2=A0 * values. These saved addresses will be used= for freeing >> +=C2=A0=C2=A0=C2=A0=C2=A0 * page table pages. >> +=C2=A0=C2=A0=C2=A0=C2=A0 */ >> +=C2=A0=C2=A0=C2=A0 pmd =3D READ_ONCE(*pmdp); >> +=C2=A0=C2=A0=C2=A0 saved_p4dp =3D p4d_offset(pgdp, 0UL); >> +=C2=A0=C2=A0=C2=A0 saved_pudp =3D pud_offset(p4dp, 0UL); >> +=C2=A0=C2=A0=C2=A0 saved_pmdp =3D pmd_offset(pudp, 0UL); >> +=C2=A0=C2=A0=C2=A0 saved_ptep =3D pmd_pgtable(pmd); >> + >> +=C2=A0=C2=A0=C2=A0 pte_basic_tests(pte_aligned, prot); >> +=C2=A0=C2=A0=C2=A0 pmd_basic_tests(pmd_aligned, prot); >> +=C2=A0=C2=A0=C2=A0 pud_basic_tests(pud_aligned, prot); >> +=C2=A0=C2=A0=C2=A0 p4d_basic_tests(p4d_aligned, prot); >> +=C2=A0=C2=A0=C2=A0 pgd_basic_tests(pgd_aligned, prot); >> + >> +=C2=A0=C2=A0=C2=A0 pte_clear_tests(mm, ptep); >> +=C2=A0=C2=A0=C2=A0 pmd_clear_tests(mm, pmdp); >> +=C2=A0=C2=A0=C2=A0 pud_clear_tests(mm, pudp); >> +=C2=A0=C2=A0=C2=A0 p4d_clear_tests(mm, p4dp); >> +=C2=A0=C2=A0=C2=A0 pgd_clear_tests(mm, pgdp); >> + >> +=C2=A0=C2=A0=C2=A0 pte_unmap(ptep); >> + >> +=C2=A0=C2=A0=C2=A0 pmd_populate_tests(mm, pmdp, saved_ptep); >> +=C2=A0=C2=A0=C2=A0 pud_populate_tests(mm, pudp, saved_pmdp); >> +=C2=A0=C2=A0=C2=A0 p4d_populate_tests(mm, p4dp, saved_pudp); >> +=C2=A0=C2=A0=C2=A0 pgd_populate_tests(mm, pgdp, saved_p4dp); >> + >> +=C2=A0=C2=A0=C2=A0 p4d_free(mm, saved_p4dp); >> +=C2=A0=C2=A0=C2=A0 pud_free(mm, saved_pudp); >> +=C2=A0=C2=A0=C2=A0 pmd_free(mm, saved_pmdp); >> +=C2=A0=C2=A0=C2=A0 pte_free(mm, saved_ptep); >> + >> +=C2=A0=C2=A0=C2=A0 mm_dec_nr_puds(mm); >> +=C2=A0=C2=A0=C2=A0 mm_dec_nr_pmds(mm); >> +=C2=A0=C2=A0=C2=A0 mm_dec_nr_ptes(mm); >> +=C2=A0=C2=A0=C2=A0 __mmdrop(mm); >> +} >> >=20