【问题标题】:Is there any way to know the physical address of attached shared memory?有没有办法知道附加共享内存的物理地址?
【发布时间】:2017-12-08 18:34:20
【问题描述】:

我想知道 Linux 内核上新连接的共享内存的“物理”地址。

据我所知,do_shmat() 返回共享内存的“虚拟”地址。 因此,我尝试使用 TLB 转换 do_shamt() 的返回值,方法是修改内核中的 shmat,如下所示。

SYSCALL_DEFINE3(shmat, int, shmid, char __user *, shmaddr, int, shmflg)

{
    unsigned long ret; 
    unsigned long phys_ret;
    unsigned int regVal;

    long err; 

    pgd_t *pgd;
    pud_t *pud;
    pmd_t *pmd;
    pte_t *pte;

    err = do_shmat(shmid, shmaddr, shmflg, &ret, SHMLBA);
    if (err)
            return err; 
    force_successful_syscall_return();

    pgd = pgd_offset(current->mm, ret);
    pmd = pmd_offset(pgd, ret);
    pte = pte_offset_kernel(pmd, ret);

    printk("*pte = 0x%lx\n", *pte);

    return (long)ret;
}

但是 pte 指向的地址为 0,所以我实际上无法获得物理地址。 为什么我的代码中没有正确的 pte?

【问题讨论】:

    标签: linux arm kernel tlb


    【解决方案1】:

    试试这个:

    #include <linux/module.h>
    #include <linux/slab.h>
    #include <linux/mm.h>
    #include <linux/cma.h>
    #include <linux/dma-contiguous.h>
    #include <linux/cdev.h>
    #include <linux/sched.h>
    #include <linux/delay.h>
    #include <linux/highmem.h>
    
    /***************************************************************************************
     * phys_addr_t getPhysicalPageAddress(unsigned long va)
     *
     * Description
     *  Virtual to Physical address translation method.
     *  Performs a page walk to translate the given virtual address
     *  to its physical page address.
     *
     ***************************************************************************************/
    phys_addr_t getPhysicalPageAddress(unsigned long va)
    {
        phys_addr_t pa;
        pgd_t *pgd;
        pud_t *pud;
        pmd_t *pmd;
        pte_t *ptep , pte;
        struct page *pagina;
        struct mm_struct * mm;
        int pfn;
        pa = 0;
        mm = current->mm;
        //  Variable initialization
        pagina = NULL;
        pgd    = NULL;
        pmd    = NULL;
        ptep   = NULL;
    
        // Using Page Tables (this mechanism is known as "Page Walk"), we find the page that corresponds to Virtual Address
        pgd = pgd_offset(mm, va);
        if (!pgd_none(*pgd) || !pgd_bad(*pgd))
        {
            pud = pud_offset(pgd , va);
            if (!pud_none(*pud) || !pud_bad(*pud))
            {
                pmd = pmd_offset(pud, va);
                if (!pmd_none(*pmd) || !pmd_bad(*pmd))
                {
                    ptep = pte_offset_map(pmd, va);
                    if (ptep)
                    {
                        pte = *ptep;
                        pte_unmap(ptep);
                        pagina = pte_page(pte);
                        //  The page has been found
                        //  Seek Page Frame Number for this page
                        pfn = page_to_pfn(pagina);
                        //  Seek Physical Address for this page, using "page_to_phys()" macro
                        pa = page_to_phys(pagina);
                    } else printk(KERN_ERR, "Page Walk exception at pte entry. The Virtual Address 0x%lx cannot be translated for this process", va );
                } else printk(KERN_ERR, "Page Walk exception at pmd entry. The Virtual Address 0x%lx cannot be translated for this process", va );
            } else printk(KERN_ERR, "Page Walk exception at pud entry. The Virtual Address 0x%lx cannot be translated for this process", va );
        } else printk(KERN_ERR, "Page Walk exception at pgd entry. The Virtual Address 0x%lx cannot be translated for this process", va );
    
        return pa;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-04-05
      • 2020-09-15
      • 2011-06-22
      • 2012-10-03
      • 1970-01-01
      • 2020-09-24
      • 2021-11-20
      相关资源
      最近更新 更多