如何从Linux内核模块中的逻辑地址获取物理地址? [英] How to get the physical address from the logical one in a Linux kernel module?

查看:160
本文介绍了如何从Linux内核模块中的逻辑地址获取物理地址?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

除了手动浏览页面目录条目之外,是否有任何适当的方法可以通过逻辑地址获取物理地址?我在内核的源代码中寻找了此功能,发现有一个follow_page函数可以很好地利用内置的巨大和透明页面支持.但是它没有导出到内核模块(为什么?)...

Is there any suitable way to get the physical address by the logical one except to walk through page directory entries by hand? I've looked for this functionality in kernel's sources and found that there is a follow_page function that do it well with built-in huge and transparent-huge pages support. But it's not exported to kernel modules (why???)...

所以,我不想发明轮子,我认为用手重新实现follow_page功能不是很好.

So, I don't want to invent the wheel and I think that it's not very good to reimplement the follow_page functionality by hand.

推荐答案

好吧,它看起来像是这样(从虚拟地址开始跟随PTE):

Well, it might looks as something like that (follow PTE from an virtual address):

void follow_pte(struct mm_struct * mm, unsigned long address, pte_t * entry)
{
    pgd_t * pgd = pgd_offset(mm, address);

    printk("follow_pte() for %lx\n", address);

    entry->pte = 0;
    if (!pgd_none(*pgd) && !pgd_bad(*pgd)) {
        pud_t * pud = pud_offset(pgd, address);
        struct vm_area_struct * vma = find_vma(mm, address);

        printk(" pgd = %lx\n", pgd_val(*pgd));

        if (pud_none(*pud)) {
            printk("  pud = empty\n");
            return;
        }
        if (pud_huge(*pud) && vma->vm_flags & VM_HUGETLB) {
            entry->pte = pud_val(*pud);
            printk("  pud = huge\n");
            return;
        }

        if (!pud_bad(*pud)) {
            pmd_t * pmd = pmd_offset(pud, address);

            printk("  pud = %lx\n", pud_val(*pud));

            if (pmd_none(*pmd)) {
                printk("   pmd = empty\n");
                return;
            }
            if (pmd_huge(*pmd) && vma->vm_flags & VM_HUGETLB) {
                entry->pte = pmd_val(*pmd);
                printk("   pmd = huge\n");
                return;
            }
            if (pmd_trans_huge(*pmd)) {
                entry->pte = pmd_val(*pmd);
                printk("   pmd = trans_huge\n");
                return;
            }
            if (!pmd_bad(*pmd)) {
                pte_t * pte = pte_offset_map(pmd, address);

                printk("   pmd = %lx\n", pmd_val(*pmd));

                if (!pte_none(*pte)) {
                    entry->pte = pte_val(*pte);
                    printk("    pte = %lx\n", pte_val(*pte));
                } else {
                    printk("    pte = empty\n");
                }
                pte_unmap(pte);
            }
        }
    }
}

这篇关于如何从Linux内核模块中的逻辑地址获取物理地址?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆