All of lore.kernel.org
 help / color / mirror / Atom feed
* Reversing a memory mapping?
@ 2011-02-03 20:50 Nikolaus Rath
  2011-02-05 21:04 ` virt_to_page for userspace pointers (was: Reversing a memory mapping?) Nikolaus Rath
  0 siblings, 1 reply; 10+ messages in thread
From: Nikolaus Rath @ 2011-02-03 20:50 UTC (permalink / raw)
  To: linux-kernel

Hello,

I am trying to outsmart the proprietary nvidia driver to get my own
driver to access to a memory region set up by the nvidia driver.

Strace tells me that the nividia userspace library is calling

mmap2(NULL, 1048576, PROT_READ|PROT_WRITE, MAP_SHARED, 5, 0x35375)

to get a userspace pointer to the kernel memory that I'm interested in.

Is there a way that my own kernel module can "reverse" this mmap call?
I.e. given the userspace pointer, how do I get access to the physical
location of the memory that has been mapped?

I know that the region is pinned and used as a DMA buffer for
communication with the GPU. I want my own device to do DMA transfers to
and from the same location.



Thanks,

   -Nikolaus

-- 
 »Time flies like an arrow, fruit flies like a Banana.«

  PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6  02CF A9AD B7F8 AE4E 425C


^ permalink raw reply	[flat|nested] 10+ messages in thread

* virt_to_page for userspace pointers (was: Reversing a memory mapping?)
  2011-02-03 20:50 Reversing a memory mapping? Nikolaus Rath
@ 2011-02-05 21:04 ` Nikolaus Rath
  2011-02-05 21:36   ` virt_to_page for userspace pointers Brice Goglin
  0 siblings, 1 reply; 10+ messages in thread
From: Nikolaus Rath @ 2011-02-05 21:04 UTC (permalink / raw)
  To: linux-kernel

Nikolaus Rath <Nikolaus@rath.org> writes:
> Is there a way that my own kernel module can "reverse" this mmap call?
> I.e. given the userspace pointer, how do I get access to the physical
> location of the memory that has been mapped?

Ok, after some studying I think I can ask the question in a better way:

Is there an equivalent function to virt_to_page (and virt_to_phys) that
works with userspace pointers? Or do I have to manually walk through the
page tables? In the later case, are there any examples of this kind of
search that I could use as a basis?


Thanks,

   -Nikolaus

-- 
 »Time flies like an arrow, fruit flies like a Banana.«

  PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6  02CF A9AD B7F8 AE4E 425C


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: virt_to_page for userspace pointers
  2011-02-05 21:04 ` virt_to_page for userspace pointers (was: Reversing a memory mapping?) Nikolaus Rath
@ 2011-02-05 21:36   ` Brice Goglin
  2011-02-13 20:24     ` Nikolaus Rath
  0 siblings, 1 reply; 10+ messages in thread
From: Brice Goglin @ 2011-02-05 21:36 UTC (permalink / raw)
  To: Nikolaus Rath; +Cc: LKML

Le 05/02/2011 22:04, Nikolaus Rath a écrit :
> Nikolaus Rath <Nikolaus@rath.org> writes:
>   
>> Is there a way that my own kernel module can "reverse" this mmap call?
>> I.e. given the userspace pointer, how do I get access to the physical
>> location of the memory that has been mapped?
>>     
> Ok, after some studying I think I can ask the question in a better way:
>
> Is there an equivalent function to virt_to_page (and virt_to_phys) that
> works with userspace pointers? Or do I have to manually walk through the
> page tables? In the later case, are there any examples of this kind of
> search that I could use as a basis?
>   

You probably want get_user_pages() (or get_user_pages_fast()).

Brice


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: virt_to_page for userspace pointers
  2011-02-05 21:36   ` virt_to_page for userspace pointers Brice Goglin
@ 2011-02-13 20:24     ` Nikolaus Rath
  2011-02-13 20:37       ` Brice Goglin
  2011-02-14 22:46       ` Nikolaus Rath
  0 siblings, 2 replies; 10+ messages in thread
From: Nikolaus Rath @ 2011-02-13 20:24 UTC (permalink / raw)
  To: Brice Goglin; +Cc: LKML

On 02/05/2011 04:36 PM, Brice Goglin wrote:
>> Is there an equivalent function to virt_to_page (and virt_to_phys) that
>> works with userspace pointers? Or do I have to manually walk through the
>> page tables? In the later case, are there any examples of this kind of
>> search that I could use as a basis?
>>   
> 
> You probably want get_user_pages() (or get_user_pages_fast()).

Thanks for the pointer, that already helped a lot!

I would, however, prefer a more primitive function that just gives me
the struct page without locking it. And if the page is swapped out, I'd
rather get a NULL pointer than having a page frame allocated.  Is there
anything like that?

Thanks,

   -Nikolaus

-- 
 »Time flies like an arrow, fruit flies like a Banana.«

  PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6  02CF A9AD B7F8 AE4E 425C

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: virt_to_page for userspace pointers
  2011-02-13 20:24     ` Nikolaus Rath
@ 2011-02-13 20:37       ` Brice Goglin
  2011-02-13 21:56         ` Nikolaus Rath
  2011-02-14 22:46       ` Nikolaus Rath
  1 sibling, 1 reply; 10+ messages in thread
From: Brice Goglin @ 2011-02-13 20:37 UTC (permalink / raw)
  To: Nikolaus Rath; +Cc: LKML

Le 13/02/2011 21:24, Nikolaus Rath a écrit :
> On 02/05/2011 04:36 PM, Brice Goglin wrote:
>   
>>> Is there an equivalent function to virt_to_page (and virt_to_phys) that
>>> works with userspace pointers? Or do I have to manually walk through the
>>> page tables? In the later case, are there any examples of this kind of
>>> search that I could use as a basis?
>>>   
>>>       
>> You probably want get_user_pages() (or get_user_pages_fast()).
>>     
> Thanks for the pointer, that already helped a lot!
>
> I would, however, prefer a more primitive function that just gives me
> the struct page without locking it. And if the page is swapped out, I'd
> rather get a NULL pointer than having a page frame allocated.  Is there
> anything like that?
>   

If you don't lock the page, you have no guarantee that it won't get
swapped out or migrated while you look at the physical page.

Brice


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: virt_to_page for userspace pointers
  2011-02-13 20:37       ` Brice Goglin
@ 2011-02-13 21:56         ` Nikolaus Rath
  2011-02-13 22:06           ` Alan Cox
  0 siblings, 1 reply; 10+ messages in thread
From: Nikolaus Rath @ 2011-02-13 21:56 UTC (permalink / raw)
  To: Brice Goglin; +Cc: LKML

On 02/13/2011 03:37 PM, Brice Goglin wrote:
> Le 13/02/2011 21:24, Nikolaus Rath a écrit :
>> On 02/05/2011 04:36 PM, Brice Goglin wrote:
>>   
>>>> Is there an equivalent function to virt_to_page (and virt_to_phys) that
>>>> works with userspace pointers? Or do I have to manually walk through the
>>>> page tables? In the later case, are there any examples of this kind of
>>>> search that I could use as a basis?
>>>>   
>>>>       
>>> You probably want get_user_pages() (or get_user_pages_fast()).
>>>     
>> Thanks for the pointer, that already helped a lot!
>>
>> I would, however, prefer a more primitive function that just gives me
>> the struct page without locking it. And if the page is swapped out, I'd
>> rather get a NULL pointer than having a page frame allocated.  Is there
>> anything like that?
>>   
> 
> If you don't lock the page, you have no guarantee that it won't get
> swapped out or migrated while you look at the physical page.

That's fine, I know that if the page is there at all then it has been
locked by a (different) kernel driver. Is there any way to find out what
I want?


Thanks,

   -Nikolaus

-- 
 »Time flies like an arrow, fruit flies like a Banana.«

  PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6  02CF A9AD B7F8 AE4E 425C

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: virt_to_page for userspace pointers
  2011-02-13 21:56         ` Nikolaus Rath
@ 2011-02-13 22:06           ` Alan Cox
  2011-02-13 22:11             ` Nikolaus Rath
  0 siblings, 1 reply; 10+ messages in thread
From: Alan Cox @ 2011-02-13 22:06 UTC (permalink / raw)
  To: Nikolaus Rath; +Cc: Brice Goglin, LKML

> > If you don't lock the page, you have no guarantee that it won't get
> > swapped out or migrated while you look at the physical page.
> 
> That's fine, I know that if the page is there at all then it has been
> locked by a (different) kernel driver. Is there any way to find out what
> I want?

How do you know the other driver isn't in the middle of releasing the
page ? Doing that deep in mm code without locking inversions will be fun.

Alan

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: virt_to_page for userspace pointers
  2011-02-13 22:06           ` Alan Cox
@ 2011-02-13 22:11             ` Nikolaus Rath
  0 siblings, 0 replies; 10+ messages in thread
From: Nikolaus Rath @ 2011-02-13 22:11 UTC (permalink / raw)
  To: Alan Cox; +Cc: Brice Goglin, LKML

On 02/13/2011 05:06 PM, Alan Cox wrote:
>>> If you don't lock the page, you have no guarantee that it won't get
>>> swapped out or migrated while you look at the physical page.
>>
>> That's fine, I know that if the page is there at all then it has been
>> locked by a (different) kernel driver. Is there any way to find out what
>> I want?
> 
> How do you know the other driver isn't in the middle of releasing the
> page ? Doing that deep in mm code without locking inversions will be fun.

I have complete control over the environment, and I know that my code
will only be called after the other driver has set up the mapping and
the mapping will continue to exist until my code returns.

Please let me risk to shoot myself in the foot, just tell me if there is
a function to do so.. I take full responsibility.


Thanks,

   -Nikolaus

-- 
 »Time flies like an arrow, fruit flies like a Banana.«

  PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6  02CF A9AD B7F8 AE4E 425C

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: virt_to_page for userspace pointers
  2011-02-13 20:24     ` Nikolaus Rath
  2011-02-13 20:37       ` Brice Goglin
@ 2011-02-14 22:46       ` Nikolaus Rath
  2011-07-26 12:03         ` Alexey Skidanov
  1 sibling, 1 reply; 10+ messages in thread
From: Nikolaus Rath @ 2011-02-14 22:46 UTC (permalink / raw)
  To: linux-kernel

Nikolaus Rath <Nikolaus@rath.org> writes:
> On 02/05/2011 04:36 PM, Brice Goglin wrote:
>>> Is there an equivalent function to virt_to_page (and virt_to_phys) that
>>> works with userspace pointers? Or do I have to manually walk through the
>>> page tables? In the later case, are there any examples of this kind of
>>> search that I could use as a basis?
>>>   
>> 
>> You probably want get_user_pages() (or get_user_pages_fast()).
>
> Thanks for the pointer, that already helped a lot!
>
> I would, however, prefer a more primitive function that just gives me
> the struct page without locking it. And if the page is swapped out, I'd
> rather get a NULL pointer than having a page frame allocated.  Is there
> anything like that?

After studying the source for get_user_pages(), I believe the following
should do what I want:

    vma = find_extend_vma(current->mm, (unsigned long) data.vi_buf);
    if(vma == NULL) {
        err("find_extend_vma failed for VI.");
    }
    acq_dev->vi_pg = follow_page(vma, (unsigned long) data.vi_buf, 0);
    if(acq_dev->vi_pg == NULL) {
        err("follow_page failed for VI.");
    }

Unfortunately, I'm getting into trouble at link time when using these
functions:

  MODPOST 1 modules
WARNING: "follow_page" [/home/nikratio/control/acq196_hostdrv/acq200_hostdrv.ko] undefined!
WARNING: "find_extend_vma" [/home/nikratio/control/acq196_hostdrv/acq200_hostdrv.ko] undefined!

Can they only be used in the kernel itself, but not in kernel modules?

Thanks,

   -Nikolaus

-- 
 »Time flies like an arrow, fruit flies like a Banana.«

  PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6  02CF A9AD B7F8 AE4E 425C


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: virt_to_page for userspace pointers
  2011-02-14 22:46       ` Nikolaus Rath
@ 2011-07-26 12:03         ` Alexey Skidanov
  0 siblings, 0 replies; 10+ messages in thread
From: Alexey Skidanov @ 2011-07-26 12:03 UTC (permalink / raw)
  To: linux-kernel

Nikolaus Rath <Nikolaus <at> rath.org> writes:

> 
> Nikolaus Rath <Nikolaus <at> rath.org> writes:
> > On 02/05/2011 04:36 PM, Brice Goglin wrote:
> >>> Is there an equivalent function to virt_to_page (and virt_to_phys) that
> >>> works with userspace pointers? Or do I have to manually walk through the
> >>> page tables? In the later case, are there any examples of this kind of
> >>> search that I could use as a basis?
> >>>   
> >> 
> >> You probably want get_user_pages() (or get_user_pages_fast()).
> >
> > Thanks for the pointer, that already helped a lot!
> >
> > I would, however, prefer a more primitive function that just gives me
> > the struct page without locking it. And if the page is swapped out, I'd
> > rather get a NULL pointer than having a page frame allocated.  Is there
> > anything like that?
> 
> After studying the source for get_user_pages(), I believe the following
> should do what I want:
> 
>     vma = find_extend_vma(current->mm, (unsigned long) data.vi_buf);
>     if(vma == NULL) {
>         err("find_extend_vma failed for VI.");
>     }
>     acq_dev->vi_pg = follow_page(vma, (unsigned long) data.vi_buf, 0);
>     if(acq_dev->vi_pg == NULL) {
>         err("follow_page failed for VI.");
>     }
> 
> Unfortunately, I'm getting into trouble at link time when using these
> functions:
> 
>   MODPOST 1 modules
> WARNING: "follow_page" 
[/home/nikratio/control/acq196_hostdrv/acq200_hostdrv.ko] undefined!
> WARNING: "find_extend_vma" 
[/home/nikratio/control/acq196_hostdrv/acq200_hostdrv.ko] undefined!
> 
> Can they only be used in the kernel itself, but not in kernel modules?
> 
> Thanks,
> 
>    -Nikolaus
> 


Hi,
I had the same problem working with NVIDIA GPU driver. The NVIDIA driver mmap 
allocated memory using vm_insert_page() - allowing inserting single page into 
the vma. So you need to translate go over the whole vma and translate it page 
by page. I just implemented the function to translate the virtual address to 
pfn. It mostly the same as follow_page:

/**
 * This function walks through page tables and get the PFN of virtual address
 */
long get_pfn_of_virtual_address(struct vm_area_struct *vma, unsigned long 
address, unsigned long& pfn) {

    pgd_t *pgd;
    pud_t *pud;
    pmd_t *pmd;
    pte_t *ptep;
    spinlock_t *ptl;
    struct mm_struct *mm = vma->vm_mm;

    pgd = pgd_offset(mm, address);
    if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
        return -EFAULT;

    pud = pud_offset(pgd, address);
    if (pud_none(*pud) || unlikely(pud_bad(*pud)))
        return -EFAULT;

    pmd = pmd_offset(pud, address);
    if (pmd_none(*pmd))
        return -EFAULT;

    ptep = pte_offset_map_lock(mm, pmd, address, &ptl);
    pfn =  pte_pfn(*ptep);
    pte_unmap_unlock(ptep, ptl);

    return 0;

} 


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2011-07-26 12:05 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-02-03 20:50 Reversing a memory mapping? Nikolaus Rath
2011-02-05 21:04 ` virt_to_page for userspace pointers (was: Reversing a memory mapping?) Nikolaus Rath
2011-02-05 21:36   ` virt_to_page for userspace pointers Brice Goglin
2011-02-13 20:24     ` Nikolaus Rath
2011-02-13 20:37       ` Brice Goglin
2011-02-13 21:56         ` Nikolaus Rath
2011-02-13 22:06           ` Alan Cox
2011-02-13 22:11             ` Nikolaus Rath
2011-02-14 22:46       ` Nikolaus Rath
2011-07-26 12:03         ` Alexey Skidanov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.