// 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 <anshuman.khandual@arm.com>
*/
#define pr_fmt(fmt) "debug_vm_pgtable: [%-25s]: " fmt, __func__
#include <linux/gfp.h>
#include <linux/highmem.h>
#include <linux/hugetlb.h>
#include <linux/kernel.h>
#include <linux/kconfig.h>
#include <linux/memblock.h>
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/mm_types.h>
#include <linux/module.h>
#include <linux/pfn_t.h>
#include <linux/printk.h>
#include <linux/pgtable.h>
#include <linux/random.h>
#include <linux/spinlock.h>
#include <linux/swap.h>
#include <linux/swapops.h>
#include <linux/start_kernel.h>
#include <linux/sched/mm.h>
#include <linux/io.h>
#include <linux/vmalloc.h>
#include <asm/cacheflush.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
/*
* Please refer Documentation/mm/arch_pgtable_helpers.rst for the semantics
* expectations that are being validated here. All future changes in here
* or the documentation need to be in sync.
*/
#define RANDOM_NZVALUE GENMASK(7, 0)
struct pgtable_debug_args {
struct mm_struct *mm;
struct vm_area_struct *vma;
pgd_t *pgdp;
p4d_t *p4dp;
pud_t *pudp;
pmd_t *pmdp;
pte_t *ptep;
p4d_t *start_p4dp;
pud_t *start_pudp;
pmd_t *start_pmdp;
pgtable_t start_ptep;
unsigned long vaddr;
pgprot_t page_prot;
pgprot_t page_prot_none;
bool is_contiguous_page;
unsigned long pud_pfn;
unsigned long pmd_pfn;
unsigned long pte_pfn;
unsigned long fixed_alignment;
unsigned long fixed_pgd_pfn;
unsigned long fixed_p4d_pfn;
unsigned long fixed_pud_pfn;
unsigned long fixed_pmd_pfn;
unsigned long fixed_pte_pfn;
};
static void __init pte_basic_tests(struct pgtable_debug_args *args, int idx)
{
pgprot_t prot = vm_get_page_prot(idx);
pte_t pte = pfn_pte(args->fixed_pte_pfn, prot);
unsigned long val = idx, *ptr = &val;
pr_debug("Validating PTE basic (%pGv)\n", ptr);
/*
* This test needs to be executed after the given page table entry
* is created with pfn_pte() to make sure that vm_get_page_prot(idx)
* does not have the dirty bit enabled from the beginning. This is
* important for platforms like arm64 where (!PTE_RDONLY) indicate
* dirty bit being set.
*/
WARN_ON(pte_dirty(pte_