From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4D480C4345F for ; Fri, 12 Apr 2024 10:18:24 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id B0C206B0087; Fri, 12 Apr 2024 06:18:23 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id ABBC06B0089; Fri, 12 Apr 2024 06:18:23 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 95C706B008A; Fri, 12 Apr 2024 06:18:23 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0012.hostedemail.com [216.40.44.12]) by kanga.kvack.org (Postfix) with ESMTP id 73E0B6B0087 for ; Fri, 12 Apr 2024 06:18:23 -0400 (EDT) Received: from smtpin18.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay05.hostedemail.com (Postfix) with ESMTP id D1E2340E1A for ; Fri, 12 Apr 2024 10:18:22 +0000 (UTC) X-FDA: 82000480044.18.64ECF54 Received: from mail-pf1-f177.google.com (mail-pf1-f177.google.com [209.85.210.177]) by imf06.hostedemail.com (Postfix) with ESMTP id E7DB118001D for ; Fri, 12 Apr 2024 10:18:20 +0000 (UTC) Authentication-Results: imf06.hostedemail.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=aY5+8jw4; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (imf06.hostedemail.com: domain of 21cnbao@gmail.com designates 209.85.210.177 as permitted sender) smtp.mailfrom=21cnbao@gmail.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1712917101; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=balnPClGS0lbieYNX5Ohm+y5qbZnkig8pTrKOraWhOc=; b=HMGmxdPg7Jj+kQKYBIL/Gpw9VdDaykmBb+pzXKvoalREYlfiWUA2FUe2ghZmhLYwvnfCOC f5dT8I+sgM650qkZsbFao4ePq7kXw2+zQyzhte/g4eyjhteFDbkNud7EuVuvffrmg6X/JW BfMaeTh9fVpT4OUYACd8AkZYLgRYR6c= ARC-Authentication-Results: i=1; imf06.hostedemail.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=aY5+8jw4; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (imf06.hostedemail.com: domain of 21cnbao@gmail.com designates 209.85.210.177 as permitted sender) smtp.mailfrom=21cnbao@gmail.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1712917101; a=rsa-sha256; cv=none; b=kq+f6wsK9MTNviSD4QXCtwYhxjKwlRN1tyPXj4hfRajIJ05frTTD5fJd9OrYD8370fGJhs oNeDiN/QgRINDsZwBkOsBxUoVu7bLLxI4yggRnHogIJUBkUr4enBI7SGA9rx0+wIA3Ezer ef51IuMq69mqZ4SFaA3qHflh/cgP11U= Received: by mail-pf1-f177.google.com with SMTP id d2e1a72fcca58-6ecec796323so779868b3a.3 for ; Fri, 12 Apr 2024 03:18:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1712917100; x=1713521900; darn=kvack.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=balnPClGS0lbieYNX5Ohm+y5qbZnkig8pTrKOraWhOc=; b=aY5+8jw4Hwxo5foM6HJ43fwvokd167uHm4uDuIinOzNb8q26kILxwojwPX4rou8IAJ EiLH0UqWfL4so0gBQsEdma2FE8K7FvCjQpP8Di5Cv54LtBVz7qBnjOaNiFN42aPMk/bb HRuMSW7aXEWBmL6NcAdaSis1PLwRD6Q/luG22dcO3bCVsZYPuQFU2w1fYYiXwvurUmZu CamFsn9NP8d7kJRm/RtYEpdtZkEizIv05IODZNsQOsGUcLI4IAPpU0UAfdDNiJHy9y0/ PIMJxXggy+IsIzWBkKTWYfYQge5UidU3MQXE58mrUaWL7xetIqLSbJ5qygoNJAQ7MySG +fCw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712917100; x=1713521900; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=balnPClGS0lbieYNX5Ohm+y5qbZnkig8pTrKOraWhOc=; b=scG42hDlKGj+Y3mMKJiTPMRLMOdawDTEejOd0Q51VlV+V9GUjFO/Mwrg2Eb1DYHrpt YtWeTu61U4qhXP9U1s5/D/40zFZtGaXE4Ulqo6EQ3bJTFrmREo7yDJvLe/G3JXGBwH5d zRXS2SdKetDv2wib8rVxoffOwZ0ddqYUhSKVmmZECM57haE/yPmbToQsINtAgyVgR9W/ NNiC6VTWkgkjsWiMrdrpQyW6zYGbIFeR/Yeb7wIwRTtoIBZiup88v/FvPr2Ur9PHYY/D MKd+EiBeqaMN6rxmQs680WPpUuX6cho+SCmjQiLf8FugC/PACoW8j1hX9BrHNCpkCsSv ojrg== X-Forwarded-Encrypted: i=1; AJvYcCWHJW/Fi85L9wcFLcUTPGuHnoL+ngPN7l4RTWH4BhU1FwVBjxNglbA96RLK2iiDQTAEGu9AfHIyyaRZxuirBzCiqI8= X-Gm-Message-State: AOJu0YwwBpD3j0DcAFhiAeLjyIcsPOIOAC0JryhIHJeJsbq61KER03QP C+XuHrQgKGGrCWfWVmwjAke/mAjdDgEJBjvzH/QJ6pwJa5P1sriE X-Google-Smtp-Source: AGHT+IHJ3J8TAbKRluPnxrgFqD0QGB2LfDRceiz9incexd91WsZnkN3zvr6WGbMXe+JpBFLU2yb1jg== X-Received: by 2002:a05:6a20:100f:b0:1a3:a039:d11b with SMTP id gs15-20020a056a20100f00b001a3a039d11bmr2517458pzc.24.1712917099754; Fri, 12 Apr 2024 03:18:19 -0700 (PDT) Received: from localhost.localdomain ([2407:7000:8942:5500:aaa1:59ff:fe57:eb97]) by smtp.gmail.com with ESMTPSA id t24-20020a639558000000b005b7dd356f75sm2463819pgn.32.2024.04.12.03.18.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 12 Apr 2024 03:18:19 -0700 (PDT) From: Barry Song <21cnbao@gmail.com> To: ryan.roberts@arm.com Cc: 21cnbao@gmail.com, akpm@linux-foundation.org, cerasuolodomenico@gmail.com, chrisl@kernel.org, corbet@lwn.net, david@redhat.com, kasong@tencent.com, linux-kernel@vger.kernel.org, linux-mm@kvack.org, peterx@redhat.com, surenb@google.com, v-songbaohua@oppo.com, willy@infradead.org, yosryahmed@google.com, yuzhao@google.com Subject: Re: [PATCH v5 1/4] mm: add per-order mTHP anon_fault_alloc and anon_fault_fallback counters Date: Fri, 12 Apr 2024 22:17:56 +1200 Message-Id: <20240412101756.296971-1-21cnbao@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Rspamd-Server: rspam09 X-Rspamd-Queue-Id: E7DB118001D X-Stat-Signature: 6hqzg6qbnyd6qiz7r6ytdwa977qfuix8 X-Rspam-User: X-HE-Tag: 1712917100-842477 X-HE-Meta: U2FsdGVkX1/CjgaMGPjlhScwuaivAarL40nKUF0Nc2OQRmC2x1Z4wGSj0Izi9l3XOvnKKkgQO2eJEjqCjrY2zqv5Z9kQquVMm18x50GV0JZkwu+K0p8FtQW1hsvNtL8ApHYOtrZtYtnjs38PPYimLeypL8u5U1owCEGF5rknVI/GpZ+iUFWYSUKRKIuPnFRhtLws/p4cQBNlrj+BnOHPnpWIhcpMDahF6T9Tlmo5f342jQfHOr9tDxCHXfroWGKkOJkwOlTJ7L1QpqfTpojtAtvb6Ok53AVSzPnKdMQ2y1sPiuYg0YDLR9aEp2fsE0FC8cGdCWxdHuTzwjlBwP3RYnM5k67ff2Z+Y4UmEZGmY3zJKvKBPGZnNI+ZKs9uYu0qOT50+i+645Cy5g8VmbRycrLRrE3hNvWvyLK5vVZOehiPsFzYI2apeTmIoPHeH4f59wckTDwunU9w3IKrQ80b6k8TQvd9ZUZhtGlnJMrXZate4flKKuQxbdQT/AORE/ZXVIfdoIydA+fDkkGRmuoNvWfoJp9DAhW2r10XQqxUMZBUcANod0ItwLTLI+SdyCnRncH/Y9mr26L08Mc0p7ge+R3DRWtZc9t7XXcGieo0OodzehHoXUmHrKayXR+/FKDrNwFWOBY/gq9KWqs4Ots8yDG8t3L+xghIvcjnaenzi371INWsNIddM/3RJgirjlaV5HX01lsoCcqOP8MbP2cXilcU7WWNL2KCus30kVrWnTy6rucH/1b+ZVWsUZO/rcXyMoDY1Efum4GSiFZYDpY1DclU3r/5E+4lTh1ALgInMLDOJdPdL+exGkMl456s78WRB4lbDdz/8UFVmOZoAjFQFhkjTvTKeuXqrtphr5zOyzX8J1e/I40roPMiCjmu2HuYqMhHEBBfiNINmw+VrnlgbZ4jtVP/FMFDXv3zykZImu8Otzbm25ltDCy/6vxAdtd9bUC/KMDTGz2CnRBr7yh gL0EWRRb F9+LKJ4k91UtPNNdrlELfPoe7IArfa+aKd6hH4D2/VgAEcw4g6KQI/vxCRyAako/XccZ1EQbOeR/5wf8sYWMfYn7FUuAL+zGa2JRwdtaiWGdoOdQehND0Bl9ocUggr7QLYgnOg4QL7mDa3iAgzPOURYmYADlkLaN5/e753RMqy8A5Hsg12QTgc/5UtzZxBq8LQ1fkA1Bz+7sF4kS+KHkGkSFRtp1I/v6Woa6QbM8axozQw37zW9KW0n2KKRXtQ/5mPQGo5y5feBrGG5Vasqn4RSZ+vOR/N9GRVuKsdT4/dczf+201XofaFm1ygUoH/bL9XtzGMhNG4Y/03cMZ+vTY+1j80O5lBL6usnWOKIdSaYSKCY+cXhkR0FFAaj6f+yWxM+LPA1b/QQvsMlNuxVzkmrJJKYJS/JNnWzDux9xB1cxXTCCmiolszZSwqHV6/WXZf0sSPmJ5OQHpCKJ7rq9VGqNrqeFuHWSl7g+kd+GjuVjk0jTgKid5SfgJocWAQNvvYxD2K8r8F5b0Gl5NEEGzuRgisKLwunqViTSumKEHwYmZQV/8e/09M+9LujSc8+YEyO19/+7lbz4ANM3w0rFtnbabblwYlMSdcGMO8FMSFy6JVZShqbYUygbd0alKF0kLSIKPpvkBt7BOPC8sQ8ysb8SlbPqK0JNzMWXU5+uxHxgpJ2QB/UmmkQIxlmITSX8bCVde5wBT9nKPTLcUVcYiz3FQYOEdvFqdtiUKO1pTy9k6v8KTt4ZkJAD2JiKMPo4zHHK/AosPV0TpRP2/C7fc5ndaHEML/mVB1/OGO7HOkWvOOORFW17YK3A9y4s5Q5GYea5y4uOeY7rbZ99D2j/yC+p2iCrSr3FHvTO3fa4dHmQhjNkGbQf4vfpDFA== 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: List-Subscribe: List-Unsubscribe: On Fri, Apr 12, 2024 at 9:56 PM Ryan Roberts wrote: > > On 12/04/2024 10:43, Barry Song wrote: > > On Fri, Apr 12, 2024 at 9:27 PM Ryan Roberts wrote: > >> > >> Hi Barry, > >> > >> 2 remaining comments - otherwise looks good. (same comments I just made in the > >> v4 conversation). > >> > >> On 12/04/2024 08:37, Barry Song wrote: > >>> From: Barry Song > >>> > >>> Profiling a system blindly with mTHP has become challenging due to the > >>> lack of visibility into its operations.  Presenting the success rate of > >>> mTHP allocations appears to be pressing need. > >>> > >>> Recently, I've been experiencing significant difficulty debugging > >>> performance improvements and regressions without these figures.  It's > >>> crucial for us to understand the true effectiveness of mTHP in real-world > >>> scenarios, especially in systems with fragmented memory. > >>> > >>> This patch establishes the framework for per-order mTHP > >>> counters. It begins by introducing the anon_fault_alloc and > >>> anon_fault_fallback counters. Additionally, to maintain consistency > >>> with thp_fault_fallback_charge in /proc/vmstat, this patch also tracks > >>> anon_fault_fallback_charge when mem_cgroup_charge fails for mTHP. > >>> Incorporating additional counters should now be straightforward as well. > >>> > >>> Signed-off-by: Barry Song > >>> Cc: Chris Li > >>> Cc: David Hildenbrand > >>> Cc: Domenico Cerasuolo > >>> Cc: Kairui Song > >>> Cc: Matthew Wilcox (Oracle) > >>> Cc: Peter Xu > >>> Cc: Ryan Roberts > >>> Cc: Suren Baghdasaryan > >>> Cc: Yosry Ahmed > >>> Cc: Yu Zhao > >>> --- > >>>  include/linux/huge_mm.h | 51 ++++++++++++++++++++++++++++++++++ > >>>  mm/huge_memory.c        | 61 +++++++++++++++++++++++++++++++++++++++++ > >>>  mm/memory.c             |  3 ++ > >>>  mm/page_alloc.c         |  4 +++ > >>>  4 files changed, 119 insertions(+) > >>> > >>> diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h > >>> index e896ca4760f6..c5beb54b97cb 100644 > >>> --- a/include/linux/huge_mm.h > >>> +++ b/include/linux/huge_mm.h > >>> @@ -264,6 +264,57 @@ unsigned long thp_vma_allowable_orders(struct vm_area_struct *vma, > >>>                                         enforce_sysfs, orders); > >>>  } > >>> > >>> +enum mthp_stat_item { > >>> +     MTHP_STAT_ANON_FAULT_ALLOC, > >>> +     MTHP_STAT_ANON_FAULT_FALLBACK, > >>> +     MTHP_STAT_ANON_FAULT_FALLBACK_CHARGE, > >>> +     __MTHP_STAT_COUNT > >>> +}; > >>> + > >>> +struct mthp_stat { > >>> +     unsigned long stats[0][__MTHP_STAT_COUNT]; > >>> +}; > >>> + > >>> +extern struct mthp_stat __percpu *mthp_stats; > >>> + > >>> +static inline void count_mthp_stat(int order, enum mthp_stat_item item) > >>> +{ > >>> +     if (order <= 0 || order > PMD_ORDER || !mthp_stats) > >>> +             return; > >>> + > >>> +     this_cpu_inc(mthp_stats->stats[order][item]); > >>> +} > >>> + > >>> +static inline void count_mthp_stats(int order, enum mthp_stat_item item, long delta) > >>> +{ > >>> +     if (order <= 0 || order > PMD_ORDER || !mthp_stats) > >>> +             return; > >>> + > >>> +     this_cpu_add(mthp_stats->stats[order][item], delta); > >>> +} > >>> + > >>> +/* > >>> + * Fold the foreign cpu mthp stats into our own. > >>> + * > >>> + * This is adding to the stats on one processor > >>> + * but keeps the global counts constant. > >>> + */ > >>> +static inline void mthp_stats_fold_cpu(int cpu) > >>> +{ > >>> +     struct mthp_stat *fold_stat; > >>> +     int i, j; > >>> + > >>> +     if (!mthp_stats) > >>> +             return; > >>> +     fold_stat = per_cpu_ptr(mthp_stats, cpu); > >>> +     for (i = 1; i <= PMD_ORDER; i++) { > >>> +             for (j = 0; j < __MTHP_STAT_COUNT; j++) { > >>> +                     count_mthp_stats(i, j, fold_stat->stats[i][j]); > >>> +                     fold_stat->stats[i][j] = 0; > >>> +             } > >>> +     } > >>> +} > >> > >> This is a pretty horrible hack; I'm pretty sure just summing for all *possible* > >> cpus should work. > >> > >>> + > >>>  #define transparent_hugepage_use_zero_page()                         \ > >>>       (transparent_hugepage_flags &                                   \ > >>>        (1< >>> diff --git a/mm/huge_memory.c b/mm/huge_memory.c > >>> index dc30139590e6..21c4ac74b484 100644 > >>> --- a/mm/huge_memory.c > >>> +++ b/mm/huge_memory.c > >>> @@ -526,6 +526,50 @@ static const struct kobj_type thpsize_ktype = { > >>>       .sysfs_ops = &kobj_sysfs_ops, > >>>  }; > >>> > >>> +struct mthp_stat __percpu *mthp_stats; > >>> + > >>> +static unsigned long sum_mthp_stat(int order, enum mthp_stat_item item) > >>> +{ > >>> +     unsigned long sum = 0; > >>> +     int cpu; > >>> + > >>> +     cpus_read_lock(); > >>> +     for_each_online_cpu(cpu) { > >>> +             struct mthp_stat *this = per_cpu_ptr(mthp_stats, cpu); > >>> + > >>> +             sum += this->stats[order][item]; > >>> +     } > >>> +     cpus_read_unlock(); > >>> + > >>> +     return sum; > >>> +} > >>> + > >>> +#define DEFINE_MTHP_STAT_ATTR(_name, _index)                                 \ > >>> +static ssize_t _name##_show(struct kobject *kobj,                    \ > >>> +                     struct kobj_attribute *attr, char *buf)         \ > >>> +{                                                                    \ > >>> +     int order = to_thpsize(kobj)->order;                            \ > >>> +                                                                     \ > >>> +     return sysfs_emit(buf, "%lu\n", sum_mthp_stat(order, _index));  \ > >>> +}                                                                    \ > >>> +static struct kobj_attribute _name##_attr = __ATTR_RO(_name) > >>> + > >>> +DEFINE_MTHP_STAT_ATTR(anon_fault_alloc, MTHP_STAT_ANON_FAULT_ALLOC); > >>> +DEFINE_MTHP_STAT_ATTR(anon_fault_fallback, MTHP_STAT_ANON_FAULT_FALLBACK); > >>> +DEFINE_MTHP_STAT_ATTR(anon_fault_fallback_charge, MTHP_STAT_ANON_FAULT_FALLBACK_CHARGE); > >>> + > >>> +static struct attribute *stats_attrs[] = { > >>> +     &anon_fault_alloc_attr.attr, > >>> +     &anon_fault_fallback_attr.attr, > >>> +     &anon_fault_fallback_charge_attr.attr, > >>> +     NULL, > >>> +}; > >>> + > >>> +static struct attribute_group stats_attr_group = { > >>> +     .name = "stats", > >>> +     .attrs = stats_attrs, > >>> +}; > >>> + > >>>  static struct thpsize *thpsize_create(int order, struct kobject *parent) > >>>  { > >>>       unsigned long size = (PAGE_SIZE << order) / SZ_1K; > >>> @@ -549,6 +593,12 @@ static struct thpsize *thpsize_create(int order, struct kobject *parent) > >>>               return ERR_PTR(ret); > >>>       } > >>> > >>> +     ret = sysfs_create_group(&thpsize->kobj, &stats_attr_group); > >>> +     if (ret) { > >>> +             kobject_put(&thpsize->kobj); > >>> +             return ERR_PTR(ret); > >>> +     } > >>> + > >>>       thpsize->order = order; > >>>       return thpsize; > >>>  } > >>> @@ -691,6 +741,11 @@ static int __init hugepage_init(void) > >>>        */ > >>>       MAYBE_BUILD_BUG_ON(HPAGE_PMD_ORDER < 2); > >>> > >>> +     mthp_stats = __alloc_percpu((PMD_ORDER + 1) * sizeof(mthp_stats->stats[0]), > >>> +                     sizeof(unsigned long)); > >> > >> Personally I think it would be cleaner to allocate statically using > >> ilog2(MAX_PTRS_PER_PTE) instead of PMD_ORDER. > > > > Hi Ryan, > > > > I don't understand why MAX_PTRS_PER_PTE is the correct size. For ARM64, > > > > #define PMD_ORDER       (PMD_SHIFT - PAGE_SHIFT) > > > > #define MAX_PTRS_PER_PTE PTRS_PER_PTE > > > > #define PTRS_PER_PTE            (1 << (PAGE_SHIFT - 3)) > > > > while PAGE_SIZE is 16KiB or 64KiB, PTRS_PER_PTE can be a huge number? > > > > > > Am I missing something? > > PTRS_PER_PTE is the number of PTE entries in a PTE table. On arm64 its as follows: > > PAGE_SIZE       PAGE_SHIFT      PTRS_PER_PTE > 4K              12              512 > 16K             14              2048 > 64K             16              8192 > > So (PTRS_PER_PTE * PAGE_SIZE) = PMD_SIZE > > PMD_ORDER is ilog2(PMD_SIZE / PAGE_SIZE) = ilog2(PTRS_PER_PTE) > > MAX_PTRS_PER_PTE is just the maximum value that PTRS_PER_PTE will ever have, > (and its equal to PTRS_PER_PTE except for powerpc). > > Pretty sure the math is correct? I am not convinced the math is correct :-) while page size is 64KiB, the page table is as below, PMD_ORDER = L2 index bits = [41:29] = 13 != ilog2(8192) +--------+--------+--------+--------+--------+--------+--------+--------+ |63 56|55 48|47 40|39 32|31 24|23 16|15 8|7 0| +--------+--------+--------+--------+--------+--------+--------+--------+ | | | | | | | | | v | | | | [15:0] in-page offset | | | +----------> [28:16] L3 index | | +--------------------------> [41:29] L2 index | +-------------------------------> [47:42] L1 index (48-bit) | [51:42] L1 index (52-bit) +-------------------------------------------------> [63] TTBR0/1 while page size is 4KiB, the page table is as below, +--------+--------+--------+--------+--------+--------+--------+--------+ |63 56|55 48|47 40|39 32|31 24|23 16|15 8|7 0| +--------+--------+--------+--------+--------+--------+--------+--------+ | | | | | | | | | | | v | | | | | [11:0] in-page offset | | | | +-> [20:12] L3 index | | | +-----------> [29:21] L2 index | | +---------------------> [38:30] L1 index | +-------------------------------> [47:39] L0 index +-------------------------------------------------> [63] TTBR0/1 PMD_ORDER = L2 index bits = [29:21] = 9 = ilog2(512). You are only correct while page size = 4KiB.