On Fri, Dec 8, 2023 at 1:12 PM Christoph Lameter (Ampere) <cl@xxxxxxxxxx> wrote: > > X86 has information in /proc/meminfo showing the use of large mappings > for the kernel direct map. This has now also become important for > ARM since the kernel default CONFIG_RODATA_FULL_DEFAULT_ENABLED > forces 4K PTE use for the direct map and users may not be aware > of the performance impact of the increased TLB use etc. > > The output of /proc/meminfo on ARM64 is then after this patch: > > 4K page size: > > Hugepagesize: 2048 kB > Hugetlb: 0 kB > DirectMap4k: 155912 kB > CONT DMap4k: 1176 kB > DirectMap2M: 722944 kB > CONT DMap2M: 28672 kB > DirectMap1G: 534773760 kB > > 64K page size: > > Hugepagesize: 524288 kB > Hugetlb: 0 kB > DirectMap64k: 882624 kB > CONT DMap64k: 19904 kB > DirectMap512M: 534773760 kB > CONT DMap512M: 0 kB > DirectMap4096G: 0 kB > > Signed-off-by: Christoph Lameter <cl@xxxxxxxxx> > > Index: linux/arch/arm64/mm/mmu.c > =================================================================== > --- linux.orig/arch/arm64/mm/mmu.c > +++ linux/arch/arm64/mm/mmu.c > @@ -66,6 +66,12 @@ u32 __boot_cpu_mode[] = { BOOT_CPU_MODE_ > */ > long __section(".mmuoff.data.write") __early_cpu_boot_status; > > +static atomic_t nr_pte; > +static atomic_t nr_pmd; > +static atomic_t nr_pud; > +static atomic_t nr_pte_cont; > +static atomic_t nr_pmd_cont; These statistics are useful for debugging. However, why not use the direct_pages_count[] array to save the counters like other architectures, for example, x86, ppc and s390? > + > /* > * Empty_zero_page is a special page that is used for zero-initialized data > * and COW. > @@ -179,6 +185,7 @@ static void init_pte(pmd_t *pmdp, unsign > pte_t old_pte = READ_ONCE(*ptep); > > set_pte(ptep, pfn_pte(__phys_to_pfn(phys), prot)); > + atomic_inc(&nr_pte); > > /* > * After the PTE entry has been populated once, we > @@ -223,8 +230,10 @@ static void alloc_init_cont_pte(pmd_t *p > > /* use a contiguous mapping if the range is suitably aligned */ > if ((((addr | next | phys) & ~CONT_PTE_MASK) == 0) && > - (flags & NO_CONT_MAPPINGS) == 0) > + (flags & NO_CONT_MAPPINGS) == 0) { > __prot = __pgprot(pgprot_val(prot) | PTE_CONT); > + atomic_inc(&nr_pte_cont); > + } > > init_pte(pmdp, addr, next, phys, __prot); > > @@ -249,6 +258,7 @@ static void init_pmd(pud_t *pudp, unsign > if (((addr | next | phys) & ~PMD_MASK) == 0 && > (flags & NO_BLOCK_MAPPINGS) == 0) { > pmd_set_huge(pmdp, phys, prot); > + atomic_inc(&nr_pmd); > > /* > * After the PMD entry has been populated once, we > @@ -301,8 +311,10 @@ static void alloc_init_cont_pmd(pud_t *p > > /* use a contiguous mapping if the range is suitably aligned */ > if ((((addr | next | phys) & ~CONT_PMD_MASK) == 0) && > - (flags & NO_CONT_MAPPINGS) == 0) > + (flags & NO_CONT_MAPPINGS) == 0) { > __prot = __pgprot(pgprot_val(prot) | PTE_CONT); > + atomic_inc(&nr_pmd_cont); > + } > > init_pmd(pudp, addr, next, phys, __prot, pgtable_alloc, flags); > > @@ -346,7 +358,7 @@ static void alloc_init_pud(pgd_t *pgdp, > ((addr | next | phys) & ~PUD_MASK) == 0 && > (flags & NO_BLOCK_MAPPINGS) == 0) { > pud_set_huge(pudp, phys, prot); > - > + atomic_inc(&nr_pud); > /* > * After the PUD entry has been populated once, we > * only allow updates to the permission attributes. > @@ -1486,3 +1498,35 @@ void ptep_modify_prot_commit(struct vm_a > { > set_pte_at(vma->vm_mm, addr, ptep, pte); > } > + > +#ifdef CONFIG_PROC_FS > +void arch_report_meminfo(struct seq_file *m) > +{ > + unsigned long pagesize_in_kb = PAGE_SIZE / 1024; > + > + seq_printf(m, "DirectMap%luk: %8lu kB\n", > + pagesize_in_kb, > + (unsigned long)atomic_read(&nr_pte) * pagesize_in_kb); > + > + seq_printf(m, "CONT DMap%luk: %8lu kB\n", > + pagesize_in_kb, > + (unsigned long)atomic_read(&nr_pte_cont) * pagesize_in_kb); > + > + pagesize_in_kb = PMD_SIZE / 1024; > + > + seq_printf(m, "DirectMap%luM: %8lu kB\n", > + pagesize_in_kb / 1024, > + (unsigned long)atomic_read(&nr_pmd) * pagesize_in_kb); > + > + seq_printf(m, "CONT DMap%luM: %8lu kB\n", > + pagesize_in_kb / 1024, > + (unsigned long)atomic_read(&nr_pmd_cont) * pagesize_in_kb); > + > + pagesize_in_kb = PUD_SIZE / 1024; > + > + seq_printf(m, "DirectMap%luG: %10lu kB\n", > + pagesize_in_kb >> 20, > + (unsigned long)atomic_read(&nr_pud) * pagesize_in_kb); > +} > +#endif > + >