Re: How to read Page Table Entry in the linux kernel module?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, May 28, 2008 at 7:11 PM, sahlot arvind <asahlot@xxxxxxxxx> wrote:
> I am working on Linux 2.6 and inside the init function of my module I am
> doing this -
>
> -------------
> init_module ()
> {
>      va = kmalloc (4096, GFP_KERNEL);
> }
> --------------
>
> Now I want to read the page table entry for this va?
> What is the right way to do that?
> Thanks in advance
> - A
>
Actually, specifically for your question, the kernel is already doing
it - as I just found out :-)...and the answer is non-trivial:

Lookup in arch/x86/mm/fault.c:

static void dump_pagetable(unsigned long address)
{
#ifdef CONFIG_X86_32
        __typeof__(pte_val(__pte(0))) page;

        page = read_cr3();
        page = ((__typeof__(page) *) __va(page))[address >> PGDIR_SHIFT];
#ifdef CONFIG_X86_PAE
        printk("*pdpt = %016Lx ", page);
        if ((page >> PAGE_SHIFT) < max_low_pfn
            && page & _PAGE_PRESENT) {
                page &= PAGE_MASK;
                page = ((__typeof__(page) *) __va(page))[(address >> PMD_SHIFT)
                                                         & (PTRS_PER_PMD - 1)];
                printk(KERN_CONT "*pde = %016Lx ", page);
                page &= ~_PAGE_NX;
        }
#else
        printk("*pde = %08lx ", page);
#endif

        /*
         * We must not directly access the pte in the highpte
         * case if the page table is located in highmem.
         * And let's rather not kmap-atomic the pte, just in case
         * it's allocated already.
         */
        if ((page >> PAGE_SHIFT) < max_low_pfn
            && (page & _PAGE_PRESENT)
            && !(page & _PAGE_PSE)) {
                page &= PAGE_MASK;
                page = ((__typeof__(page) *) __va(page))[(address >> PAGE_SHIFT)
                                                         & (PTRS_PER_PTE - 1)];
                printk("*pte = %0*Lx ", sizeof(page)*2, (u64)page);
        }

        printk("\n");
#else /* CONFIG_X86_64 */
        pgd_t *pgd;
        pud_t *pud;
        pmd_t *pmd;
        pte_t *pte;

        pgd = (pgd_t *)read_cr3();

        pgd = __va((unsigned long)pgd & PHYSICAL_PAGE_MASK);
        pgd += pgd_index(address);
        if (bad_address(pgd)) goto bad;
        printk("PGD %lx ", pgd_val(*pgd));
        if (!pgd_present(*pgd)) goto ret;

        pud = pud_offset(pgd, address);
        if (bad_address(pud)) goto bad;
        printk("PUD %lx ", pud_val(*pud));
        if (!pud_present(*pud) || pud_large(*pud))
                goto ret;

        pmd = pmd_offset(pud, address);
        if (bad_address(pmd)) goto bad;
        printk("PMD %lx ", pmd_val(*pmd));
        if (!pmd_present(*pmd) || pmd_large(*pmd)) goto ret;

        pte = pte_offset_kernel(pmd, address);
        if (bad_address(pte)) goto bad;
        printk("PTE %lx", pte_val(*pte));
ret:
        printk("\n");
        return;
bad:
        printk("BAD\n");
#endif
}

Well...it is non-trivial because the function catered for different
scenario - PAE or no PAE, 64/32 bit scnenario etc.

and within this same file, there are many instances / examples of
deriving the PTE from the kernel virtual address.

-- 
Regards,
Peter Teoh

--
To unsubscribe from this list: send an email with
"unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx
Please read the FAQ at http://kernelnewbies.org/FAQ


[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux