Newer
Older
advsyssoft / pagetable / pagetable.c
@Motoki Miura Motoki Miura on 13 Nov 2020 1 KB first
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <asm/pgtable.h>

static unsigned int processid = 1;
module_param(processid, uint, 0);
static unsigned long addr = 0;
module_param(addr, ulong, 0);

static unsigned long get_pfndata(unsigned long entry) {
	entry &= 0x000FFFFFFFFFF000;
	return(entry >>= 12);
}

static int __init pagetable_init(void) {
	pgd_t *pgd;
	p4d_t *p4d;
	pud_t *pud;
	pmd_t *pmd;
	pte_t *pte;
	unsigned long paddr;
	struct pid *pid = find_get_pid(processid);
	struct task_struct *task = pid_task(pid, PIDTYPE_PID);
	struct mm_struct *mm = task->mm;
	if (pid == NULL) return 0;

	printk("mm->pgd   = %016lx\n", (unsigned long)mm->pgd);
	printk("CR3       = %010lx\n", get_pfndata(__pa(mm->pgd)));
	pgd = pgd_offset(mm, addr);
	if (pgd_none(*pgd) || pgd_bad(*pgd)) return 0;
	printk("PGD entry = %010lx\n", get_pfndata(pgd_val(*pgd)));

	p4d = p4d_offset(pgd, addr);
	if (p4d_none(*p4d) || p4d_bad(*p4d)) return 0;
	printk("P4D entry = %010lx\n", get_pfndata(p4d_val(*p4d)));
	
	pud = pud_offset(p4d, addr);
	if (pud_none(*pud) || pud_bad(*pud)) return 0;
	printk("PUD entry = %010lx\n", get_pfndata(pud_val(*pud)));

	pmd = pmd_offset(pud, addr);
	if (pmd_none(*pmd) || pmd_bad(*pmd)) return 0;
	printk("PMD entry = %010lx\n", get_pfndata(pmd_val(*pmd)));

	pte = pte_offset_map(pmd, addr);
	if (pte_none(*pte)) return 0;
	paddr = pte_val(*pte);
	printk("PTE entry = %010lx\n", get_pfndata(paddr));
	paddr = (paddr & 0x000FFFFFFFFFF000) | (addr & 0xFFF);
	printk("Phys addr = %016lx\n", paddr);
	
  	return 0;
}
static void __exit pagetable_exit(void) {
}
module_init(pagetable_init);
module_exit(pagetable_exit);
MODULE_AUTHOR("SUEYASU Taizo");
MODULE_DESCRIPTION("pagetable test driver");
MODULE_LICENSE("GPL");
MODULE_PARM_DESC(processid, "PID (0 < processid < 2^22, default=1)");
MODULE_PARM_DESC(addr, "Virtual address, default=0");