Message ID | 20231017005300.334140-1-gshan@redhat.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:612c:2908:b0:403:3b70:6f57 with SMTP id ib8csp3819810vqb; Mon, 16 Oct 2023 17:54:14 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFCvj2NPXBYHL4AF507tmWckplaIB4CYo4dLmTGdonPHxq9VxCnCWqt6Yg8sl44w1Nw/LEx X-Received: by 2002:a05:6a00:6008:b0:68f:c309:9736 with SMTP id fo8-20020a056a00600800b0068fc3099736mr750876pfb.3.1697504053877; Mon, 16 Oct 2023 17:54:13 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1697504053; cv=none; d=google.com; s=arc-20160816; b=Ujb95qPL5J1hGhnqurzalYWBFvqO2LWT3xnXuDsX3xabhrLY7PZO08If6QOTbi5E2G PJs80/QZWf1L+atghjEN0n6u/tCpCz/eGxmdC3QBA1Z7Su7Zmf90KIaCiyJzO3v/dsnW uac2yFdzsvzzHGdXdWxP6ZcGq965BkNMD7myhpURuAE0lKZT5Vw2C/x93j06vA77kuiS xVM1jdtUFtFW/XY7UCiTT7NmHs3tdK+50rC07Nx8AOS3d/VgUBoKTXYzkbLYAIzTTH3N n/IpfYf5qajnQT098dekuUOY+JTggwHpnVhCG8SdPLsAD4uhrNL9HDGJLsyM1RBTf9Up 6qjQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from:dkim-signature; bh=FVYfxxgypJNUOYWqlo9r89JsXo7lPpAWq0cYDAv2yF0=; fh=35qS1zR4nJl4UAp23/QWQ6efWfwmlWoeTA+EA/p7hhY=; b=rcipSFGKBGdXoAX457i5KK6KCs2ySh2djZE7ThJZhaxAc9nQh4Ky3cN5w338Z7kIZd remKeo+qSmkLA2+/DBhMnxv5ojB7c/yMfBO1HodEfMeTWif6DghnlfVcpVoMuAu4HE4C kSMkLh8xWOC8Nf+kxW2EBANo5883aaWhi50eQE3JKhKPo2/mmBL6+X7ZCBN/k0fBc3zm W3W65x69ExeYTzTfZjcRM5ntQ4TugzccE6AKNyjLcf0WHudPWLhvJGj+sVQPieOVW709 KsfCC5Q8NfkaHFssmQwMcuDPVIx2IIWhSlgzbVokH8ttF2rk1nb2AkCj77+TIQ29tozW BYGw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=grk8m27y; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:7 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from snail.vger.email (snail.vger.email. [2620:137:e000::3:7]) by mx.google.com with ESMTPS id p20-20020a056a000a1400b006b905fe37b7si446578pfh.221.2023.10.16.17.54.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Oct 2023 17:54:13 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:7 as permitted sender) client-ip=2620:137:e000::3:7; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=grk8m27y; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:7 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by snail.vger.email (Postfix) with ESMTP id 63FFD80D6E6D; Mon, 16 Oct 2023 17:54:12 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at snail.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234181AbjJQAyJ (ORCPT <rfc822;hjfbswb@gmail.com> + 18 others); Mon, 16 Oct 2023 20:54:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59198 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233549AbjJQAyI (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Mon, 16 Oct 2023 20:54:08 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C98F7AB for <linux-kernel@vger.kernel.org>; Mon, 16 Oct 2023 17:53:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1697503998; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=FVYfxxgypJNUOYWqlo9r89JsXo7lPpAWq0cYDAv2yF0=; b=grk8m27yD4tWdX6vOHhkHP5j4831qJR5viSoPxpG8inE6NO0x2HtHuvDKkSYmWEstXO/R4 8Cp59cMn7mTw4E8nqFVUbuw4Ak0NkfP6mKWogvz8x4IiC5i3PKTJGZjfR8YdvSspr+/fAc 1y6poJKk2P3bygLJzB4CAC97243XsH8= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-590-i2a4zPEuMQ6T_suWUDgpzw-1; Mon, 16 Oct 2023 20:53:13 -0400 X-MC-Unique: i2a4zPEuMQ6T_suWUDgpzw-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id CA2C5185A795; Tue, 17 Oct 2023 00:53:12 +0000 (UTC) Received: from gshan.redhat.com (unknown [10.64.136.82]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 32E1840C6F79; Tue, 17 Oct 2023 00:53:09 +0000 (UTC) From: Gavin Shan <gshan@redhat.com> To: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org, catalin.marinas@arm.com, will@kernel.org, ryan.roberts@arm.com, mark.rutland@arm.com, anshuman.khandual@arm.com, shan.gavin@gmail.com Subject: [PATCH] arm64: mm: Validate CONFIG_PGTABLE_LEVELS conditionally Date: Tue, 17 Oct 2023 10:53:00 +1000 Message-ID: <20231017005300.334140-1-gshan@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (snail.vger.email [0.0.0.0]); Mon, 16 Oct 2023 17:54:12 -0700 (PDT) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1779962010692638676 X-GMAIL-MSGID: 1779962010692638676 |
Series |
arm64: mm: Validate CONFIG_PGTABLE_LEVELS conditionally
|
|
Commit Message
Gavin Shan
Oct. 17, 2023, 12:53 a.m. UTC
It's allowed for the fixmap virtual address space to span multiple
PMD entries. Instead, the address space isn't allowed to span multiple
PUD entries. However, PMD entries are folded to PUD and PGD entries
in the following combination. In this particular case, the validation
on NR_BM_PMD_TABLES should be avoided.
CONFIG_ARM64_PAGE_SHIFT = 14
CONFIG_ARM64_VA_BITS_36 = y
CONFIG_PGTABLE_LEVELS = 2
Signed-off-by: Gavin Shan <gshan@redhat.com>
---
arch/arm64/mm/fixmap.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
Comments
On Tue, Oct 17, 2023 at 10:53:00AM +1000, Gavin Shan wrote: > It's allowed for the fixmap virtual address space to span multiple > PMD entries. Instead, the address space isn't allowed to span multiple > PUD entries. However, PMD entries are folded to PUD and PGD entries > in the following combination. In this particular case, the validation > on NR_BM_PMD_TABLES should be avoided. > > CONFIG_ARM64_PAGE_SHIFT = 14 > CONFIG_ARM64_VA_BITS_36 = y > CONFIG_PGTABLE_LEVELS = 2 Is this something you found by inspection, or are you hitting a real issue on a particular config? I built a kernel with: defconfig + CONFIG_ARM64_16K_PAGES=y + CONFIG_ARM64_VA_BITS_36=y ... which gives the CONFIG_* configuration you list above, and that works just fine. For 2-level 16K pages we'd need to reserve more than 32M of fixmap slots for the assertion to fire, and we only reserve ~6M of slots in total today, so I can't see how this would be a problem unless you have 26M+ of local additions to the fixmap? Regardless of that, I don't think it's right to elide the check entirely. The point of the check is to make sure that the fixmap VA range doesn't span across multiple PMD/PUD/P4D/PGD entries, as the early_fixmap_init() and fixmap_copy() code don't handle that in general. When using 2-level 16K pages, we still want to ensure the fixmap is contained within a single PGD, and checking that it falls within a single folded PMD will check that. See the message for commit: 414c109bdf496195 ("arm64: mm: always map fixmap at page granularity") ... and the bits that deleted from early_fixmap_init(). AFAICT this is fine as-is. Mark. > > Signed-off-by: Gavin Shan <gshan@redhat.com> > --- > arch/arm64/mm/fixmap.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/arch/arm64/mm/fixmap.c b/arch/arm64/mm/fixmap.c > index c0a3301203bd..5384e5c3aeaa 100644 > --- a/arch/arm64/mm/fixmap.c > +++ b/arch/arm64/mm/fixmap.c > @@ -18,10 +18,11 @@ > > #define NR_BM_PTE_TABLES \ > SPAN_NR_ENTRIES(FIXADDR_TOT_START, FIXADDR_TOP, PMD_SHIFT) > +#if CONFIG_PGTABLE_LEVELS > 2 > #define NR_BM_PMD_TABLES \ > SPAN_NR_ENTRIES(FIXADDR_TOT_START, FIXADDR_TOP, PUD_SHIFT) > - > static_assert(NR_BM_PMD_TABLES == 1); > +#endif > > #define __BM_TABLE_IDX(addr, shift) \ > (((addr) >> (shift)) - (FIXADDR_TOT_START >> (shift))) > -- > 2.41.0 >
Hi Mark, On 10/17/23 21:05, Mark Rutland wrote: > On Tue, Oct 17, 2023 at 10:53:00AM +1000, Gavin Shan wrote: >> It's allowed for the fixmap virtual address space to span multiple >> PMD entries. Instead, the address space isn't allowed to span multiple >> PUD entries. However, PMD entries are folded to PUD and PGD entries >> in the following combination. In this particular case, the validation >> on NR_BM_PMD_TABLES should be avoided. >> >> CONFIG_ARM64_PAGE_SHIFT = 14 >> CONFIG_ARM64_VA_BITS_36 = y >> CONFIG_PGTABLE_LEVELS = 2 > > Is this something you found by inspection, or are you hitting a real issue on a > particular config? > > I built a kernel with: > > defconfig + CONFIG_ARM64_16K_PAGES=y + CONFIG_ARM64_VA_BITS_36=y > > ... which gives the CONFIG_* configuration you list above, and that works just > fine. > > For 2-level 16K pages we'd need to reserve more than 32M of fixmap slots for > the assertion to fire, and we only reserve ~6M of slots in total today, so I > can't see how this would be a problem unless you have 26M+ of local additions > to the fixmap? > > Regardless of that, I don't think it's right to elide the check entirely. > It's all about code inspection. When CONFIG_PGTABLE_LEVELS == 2, PGD/PUD/PMD are equivalent. The following two macros are interchangeable. The forthcoming static_assert() enforces that the fixmap virtual space can't span multiple PMD entries, meaning the space is limited to 32MB with above configuration. #define NR_BM_PMD_TABLES \ SPAN_NR_ENTRIES(FIXADDR_TOT_START, FIXADDR_TOP, PUD_SHIFT) #define NR_BM_PMD_TABLES \ SPAN_NR_ENTRIES(FIXADDR_TOT_START, FIXADDR_TOP, PMD_SHIFT) static_assert(NR_BM_PMD_TABLES == 1); However, multiple PTE tables are allowed. It means the fixmap virtual space can span multiple PMD entries, which is controversial to the above enforcement from the code level. Hopefully, I understood everything correctly. #define NR_BM_PTE_TABLES \ SPAN_NR_ENTRIES(FIXADDR_TOT_START, FIXADDR_TOP, PMD_SHIFT) static pte_t bm_pte[NR_BM_PTE_TABLES][PTRS_PER_PTE] __page_aligned_bss; You're correct that the following edition is needed to trigger the assert. The point is to have the fixmap virtual space larger than 32MB. enum fixed_addresses { FIX_HOLE, : FIX_PTE, FIX_PMD, FIX_PUD, FIX_PGD, FIX_DUMMY = FIX_PGD + 2048, __end_of_fixed_addresses }; > The point of the check is to make sure that the fixmap VA range doesn't span > across multiple PMD/PUD/P4D/PGD entries, as the early_fixmap_init() and > fixmap_copy() code don't handle that in general. When using 2-level 16K pages, > we still want to ensure the fixmap is contained within a single PGD, and > checking that it falls within a single folded PMD will check that. > > See the message for commit: > > 414c109bdf496195 ("arm64: mm: always map fixmap at page granularity") > > ... and the bits that deleted from early_fixmap_init(). > > AFAICT this is fine as-is. > As I can see, multiple PMD entries can be handled well in early_fixmap_init(). However, multiple PMD entries aren't handled in fixmap_copy(), as you said. early_fixmap_init early_fixmap_init_pud early_fixmap_init_pmd // multiple PMD entries handled in the loop Thanks, Gavin >> >> Signed-off-by: Gavin Shan <gshan@redhat.com> >> --- >> arch/arm64/mm/fixmap.c | 3 ++- >> 1 file changed, 2 insertions(+), 1 deletion(-) >> >> diff --git a/arch/arm64/mm/fixmap.c b/arch/arm64/mm/fixmap.c >> index c0a3301203bd..5384e5c3aeaa 100644 >> --- a/arch/arm64/mm/fixmap.c >> +++ b/arch/arm64/mm/fixmap.c >> @@ -18,10 +18,11 @@ >> >> #define NR_BM_PTE_TABLES \ >> SPAN_NR_ENTRIES(FIXADDR_TOT_START, FIXADDR_TOP, PMD_SHIFT) >> +#if CONFIG_PGTABLE_LEVELS > 2 >> #define NR_BM_PMD_TABLES \ >> SPAN_NR_ENTRIES(FIXADDR_TOT_START, FIXADDR_TOP, PUD_SHIFT) >> - >> static_assert(NR_BM_PMD_TABLES == 1); >> +#endif >> >> #define __BM_TABLE_IDX(addr, shift) \ >> (((addr) >> (shift)) - (FIXADDR_TOT_START >> (shift))) >> -- >> 2.41.0 >> >
On Wed, Oct 18, 2023 at 04:33:09PM +1000, Gavin Shan wrote: > Hi Mark, > > On 10/17/23 21:05, Mark Rutland wrote: > > On Tue, Oct 17, 2023 at 10:53:00AM +1000, Gavin Shan wrote: > > > It's allowed for the fixmap virtual address space to span multiple > > > PMD entries. Instead, the address space isn't allowed to span multiple > > > PUD entries. However, PMD entries are folded to PUD and PGD entries > > > in the following combination. In this particular case, the validation > > > on NR_BM_PMD_TABLES should be avoided. > > > > > > CONFIG_ARM64_PAGE_SHIFT = 14 > > > CONFIG_ARM64_VA_BITS_36 = y > > > CONFIG_PGTABLE_LEVELS = 2 > > > > Is this something you found by inspection, or are you hitting a real issue on a > > particular config? > > > > I built a kernel with: > > > > defconfig + CONFIG_ARM64_16K_PAGES=y + CONFIG_ARM64_VA_BITS_36=y > > > > ... which gives the CONFIG_* configuration you list above, and that works just > > fine. > > > > For 2-level 16K pages we'd need to reserve more than 32M of fixmap slots for > > the assertion to fire, and we only reserve ~6M of slots in total today, so I > > can't see how this would be a problem unless you have 26M+ of local additions > > to the fixmap? > > > > Regardless of that, I don't think it's right to elide the check entirely. > > > > It's all about code inspection. When CONFIG_PGTABLE_LEVELS == 2, PGD/PUD/PMD > are equivalent. The following two macros are interchangeable. The forthcoming > static_assert() enforces that the fixmap virtual space can't span multiple > PMD entries, meaning the space is limited to 32MB with above configuration. > > #define NR_BM_PMD_TABLES \ > SPAN_NR_ENTRIES(FIXADDR_TOT_START, FIXADDR_TOP, PUD_SHIFT) > #define NR_BM_PMD_TABLES \ > SPAN_NR_ENTRIES(FIXADDR_TOT_START, FIXADDR_TOP, PMD_SHIFT) > > static_assert(NR_BM_PMD_TABLES == 1); > > However, multiple PTE tables are allowed. It means the fixmap virtual space > can span multiple PMD entries, which is controversial to the above enforcement > from the code level. Hopefully, I understood everything correctly. > > #define NR_BM_PTE_TABLES \ > SPAN_NR_ENTRIES(FIXADDR_TOT_START, FIXADDR_TOP, PMD_SHIFT) > static pte_t bm_pte[NR_BM_PTE_TABLES][PTRS_PER_PTE] __page_aligned_bss; > The intent is that the fixmap can span multiple PTE tables, but has to fall within a single PMD table (and within a single PGD entry). See the next couple of lines where we only allocate one PMD table and one PUD table: static pte_t bm_pte[NR_BM_PTE_TABLES][PTRS_PER_PTE] __page_aligned_bss; static pmd_t bm_pmd[PTRS_PER_PMD] __page_aligned_bss __maybe_unused; static pud_t bm_pud[PTRS_PER_PUD] __page_aligned_bss __maybe_unused; The NR_BM_PMD_TABLES definition is only there for the static_assert(). > You're correct that the following edition is needed to trigger the assert. > The point is to have the fixmap virtual space larger than 32MB. It's not intended to be more than 32M. If we want to support 32M and larger, we'd need to rework the rest of the code, allocating more intermediate tables and manipulating multiple PGD entries. As we have no need for that, it's simpler to leave it as-is, with the static_assert() ther to catch if/when someone tries to expand it beyond what is supported. > > enum fixed_addresses { > FIX_HOLE, > : > FIX_PTE, > FIX_PMD, > FIX_PUD, > FIX_PGD, > FIX_DUMMY = FIX_PGD + 2048, > > __end_of_fixed_addresses > }; > > > > The point of the check is to make sure that the fixmap VA range doesn't span > > across multiple PMD/PUD/P4D/PGD entries, as the early_fixmap_init() and > > fixmap_copy() code don't handle that in general. When using 2-level 16K pages, > > we still want to ensure the fixmap is contained within a single PGD, and > > checking that it falls within a single folded PMD will check that. > > > > See the message for commit: > > > > 414c109bdf496195 ("arm64: mm: always map fixmap at page granularity") > > > > ... and the bits that deleted from early_fixmap_init(). > > > > AFAICT this is fine as-is. > > > > As I can see, multiple PMD entries can be handled well in early_fixmap_init(). > However, multiple PMD entries aren't handled in fixmap_copy(), as you said. > > early_fixmap_init > early_fixmap_init_pud > early_fixmap_init_pmd // multiple PMD entries handled in the loop If you remove the restriction of a single PMD entry, you also permit multiple PUD/P4D/PGD entries, and the early_fixmap_init() code cannot handle that. Consider how early_fixmap_init_pud() and early_fixmap_init_pmd() use bm_pud and bm_pmd respectively. As above, this code doesn't need to change: * It works today, there is no configuration where the statis_assert() fires spuriously. * If the static_assert() were to fire, we'd need to alter some portion of the code to handle that case (e.g. expanding bm_pmd and/or bm_pud, altering fixmap_copy()). * It's simpler and better to have the assertion today rather than making the code handle the currently-impossible cases. That avoids wasting memory on unusable tables, and avoids having code which is never tested. Mark.
On 10/18/23 19:42, Mark Rutland wrote: > On Wed, Oct 18, 2023 at 04:33:09PM +1000, Gavin Shan wrote: >> On 10/17/23 21:05, Mark Rutland wrote: >>> On Tue, Oct 17, 2023 at 10:53:00AM +1000, Gavin Shan wrote: >>>> It's allowed for the fixmap virtual address space to span multiple >>>> PMD entries. Instead, the address space isn't allowed to span multiple >>>> PUD entries. However, PMD entries are folded to PUD and PGD entries >>>> in the following combination. In this particular case, the validation >>>> on NR_BM_PMD_TABLES should be avoided. >>>> >>>> CONFIG_ARM64_PAGE_SHIFT = 14 >>>> CONFIG_ARM64_VA_BITS_36 = y >>>> CONFIG_PGTABLE_LEVELS = 2 >>> >>> Is this something you found by inspection, or are you hitting a real issue on a >>> particular config? >>> >>> I built a kernel with: >>> >>> defconfig + CONFIG_ARM64_16K_PAGES=y + CONFIG_ARM64_VA_BITS_36=y >>> >>> ... which gives the CONFIG_* configuration you list above, and that works just >>> fine. >>> >>> For 2-level 16K pages we'd need to reserve more than 32M of fixmap slots for >>> the assertion to fire, and we only reserve ~6M of slots in total today, so I >>> can't see how this would be a problem unless you have 26M+ of local additions >>> to the fixmap? >>> >>> Regardless of that, I don't think it's right to elide the check entirely. >>> >> >> It's all about code inspection. When CONFIG_PGTABLE_LEVELS == 2, PGD/PUD/PMD >> are equivalent. The following two macros are interchangeable. The forthcoming >> static_assert() enforces that the fixmap virtual space can't span multiple >> PMD entries, meaning the space is limited to 32MB with above configuration. >> >> #define NR_BM_PMD_TABLES \ >> SPAN_NR_ENTRIES(FIXADDR_TOT_START, FIXADDR_TOP, PUD_SHIFT) >> #define NR_BM_PMD_TABLES \ >> SPAN_NR_ENTRIES(FIXADDR_TOT_START, FIXADDR_TOP, PMD_SHIFT) >> >> static_assert(NR_BM_PMD_TABLES == 1); >> >> However, multiple PTE tables are allowed. It means the fixmap virtual space >> can span multiple PMD entries, which is controversial to the above enforcement >> from the code level. Hopefully, I understood everything correctly. >> >> #define NR_BM_PTE_TABLES \ >> SPAN_NR_ENTRIES(FIXADDR_TOT_START, FIXADDR_TOP, PMD_SHIFT) >> static pte_t bm_pte[NR_BM_PTE_TABLES][PTRS_PER_PTE] __page_aligned_bss; >> > > The intent is that the fixmap can span multiple PTE tables, but has to fall > within a single PMD table (and within a single PGD entry). See the next couple > of lines where we only allocate one PMD table and one PUD table: > > static pte_t bm_pte[NR_BM_PTE_TABLES][PTRS_PER_PTE] __page_aligned_bss; > static pmd_t bm_pmd[PTRS_PER_PMD] __page_aligned_bss __maybe_unused; > static pud_t bm_pud[PTRS_PER_PUD] __page_aligned_bss __maybe_unused; > > The NR_BM_PMD_TABLES definition is only there for the static_assert(). > Ok, thanks for the hints. >> You're correct that the following edition is needed to trigger the assert. >> The point is to have the fixmap virtual space larger than 32MB. > > It's not intended to be more than 32M. > > If we want to support 32M and larger, we'd need to rework the rest of the code, > allocating more intermediate tables and manipulating multiple PGD entries. As > we have no need for that, it's simpler to leave it as-is, with the > static_assert() ther to catch if/when someone tries to expand it beyond what is supported. > Yeah, it's a small space anyway. >> >> enum fixed_addresses { >> FIX_HOLE, >> : >> FIX_PTE, >> FIX_PMD, >> FIX_PUD, >> FIX_PGD, >> FIX_DUMMY = FIX_PGD + 2048, >> >> __end_of_fixed_addresses >> }; >> >> >>> The point of the check is to make sure that the fixmap VA range doesn't span >>> across multiple PMD/PUD/P4D/PGD entries, as the early_fixmap_init() and >>> fixmap_copy() code don't handle that in general. When using 2-level 16K pages, >>> we still want to ensure the fixmap is contained within a single PGD, and >>> checking that it falls within a single folded PMD will check that. >>> >>> See the message for commit: >>> >>> 414c109bdf496195 ("arm64: mm: always map fixmap at page granularity") >>> >>> ... and the bits that deleted from early_fixmap_init(). >>> >>> AFAICT this is fine as-is. >>> >> >> As I can see, multiple PMD entries can be handled well in early_fixmap_init(). >> However, multiple PMD entries aren't handled in fixmap_copy(), as you said. >> >> early_fixmap_init >> early_fixmap_init_pud >> early_fixmap_init_pmd // multiple PMD entries handled in the loop > > If you remove the restriction of a single PMD entry, you also permit multiple > PUD/P4D/PGD entries, and the early_fixmap_init() code cannot handle that. > Consider how early_fixmap_init_pud() and early_fixmap_init_pmd() use bm_pud and > bm_pmd respectively. > > As above, this code doesn't need to change: > > * It works today, there is no configuration where the statis_assert() fires > spuriously. > > * If the static_assert() were to fire, we'd need to alter some portion of the > code to handle that case (e.g. expanding bm_pmd and/or bm_pud, altering > fixmap_copy()). > > * It's simpler and better to have the assertion today rather than making the > code handle the currently-impossible cases. That avoids wasting memory on > unusable tables, and avoids having code which is never tested. > Agree. Please ignore my patch and lets keep it as-is. Again, it's a small space and I don't see it needs to be enlarged to hit the limit. Thanks for explaining everything in a clear way. Thanks, Gavin
diff --git a/arch/arm64/mm/fixmap.c b/arch/arm64/mm/fixmap.c index c0a3301203bd..5384e5c3aeaa 100644 --- a/arch/arm64/mm/fixmap.c +++ b/arch/arm64/mm/fixmap.c @@ -18,10 +18,11 @@ #define NR_BM_PTE_TABLES \ SPAN_NR_ENTRIES(FIXADDR_TOT_START, FIXADDR_TOP, PMD_SHIFT) +#if CONFIG_PGTABLE_LEVELS > 2 #define NR_BM_PMD_TABLES \ SPAN_NR_ENTRIES(FIXADDR_TOT_START, FIXADDR_TOP, PUD_SHIFT) - static_assert(NR_BM_PMD_TABLES == 1); +#endif #define __BM_TABLE_IDX(addr, shift) \ (((addr) >> (shift)) - (FIXADDR_TOT_START >> (shift)))