Re: How to convert virtual address to physical address and revers e?

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

 



On Mon, 28 Mar 2005 10:53:30 +0530, Thekkedath Gopakumar-agt026
<gopakumar.t@xxxxxxxxxxxx> wrote:
> 
> From: kernelnewbies-bounce@xxxxxxxxxxxx
> [mailto:kernelnewbies-bounce@xxxxxxxxxxxx]On Behalf Of P.F. Tsai
> 
> >I have problems about converting virtual address into physical address and
> >reverse. I supply a kernel function  to grab cr3 value, but how do I READ
> >the content from the address located by cr3 to load the GDT and access the
> >entry in it ?
> 
>  CR3 register holds the physical address of current process's PGD. It is
> the
> GDTR 
> register which holds the address of GDT.
>  
> 
> >static unsigned long v2p(unsigned long va)
> >{
> >  pgd_t *pgd;
> >pmd_t *pmd;
> > pte_t *ptep, pte;
> > struct page *page;
> >unsigned long pa;
> >pgd = pgd_offset(tsk->mm, va); /* what is tsk->mm */
> >pmd = pmd_offset(pgd,va);
> >pte = pte_offset(pte,va);
> >pte = *ptep;
> >page = pte_page(pte);  /* aha, we have the pa of the page  */
> >pa = (pte_val(*ptep) & PTE_PHYS_MASK) | (va&(PAGE_SIZE-1);
> >return pa;
> >}
> 
> The above function traverses the Page Directory and Page Table to get the
> physical
> address, but I do not know how safe it will be if you supply a non existant
> address 
> to it.
> 
> Linux kernel provides you with functions like virt_to_phys and friends to
> convert
> a kernel mode virtual address to physical address and vice versa.

The functions you are talking are specifically for converting the
physical addresses to kernel virtual address not to user virtual
address space, for convcerting the addresses to user address space, I
think we need to traverse the PGD and related structures as shown in
the code in earlier mail.

As I looked into the functions "virt_to_phys" and "phys_to_virt" in
page.h file, i found the following macros:

#define __PAGE_OFFSET           (0xC0000000UL)
#define PAGE_OFFSET             ((unsigned long)__PAGE_OFFSET)

#define __pa(x)                 ((unsigned long)(x)-PAGE_OFFSET)
#define __va(x)                 ((void *)((unsigned long)(x)+PAGE_OFFSET))

Actually virt_to_phys() and phys_to_virt() functions are as follows:

static inline unsigned long virt_to_phys(volatile void * address)
{
         return __pa(address);
}

static inline void * phys_to_virt(unsigned long address)
{
         return __va(address);
}

As per my understanding PAGE_OFFSET is the starting kernel virtual
address, that means kernel virtual address will start from
PAGE_OFFSET.

My question is, why we are subtracting PAGE_OFFSET from a given
address in __pa() macro, is it because physically kernel code is
placed in lower memory. If this is not the reason, can someone please
clarify this ?

> For your case, may be after you get the physical address of GDT from GDTR,
>  you can use 'ioremap' to get the mapped kernel mode virtual address and
> access
> GDTR entries with it.  Do note that the code you are writing is  extremely
> prone to
>  corrupt the system (if you alter the GDT values). I am assuming that you
> are
>  doing this for getting a better understanding of the system.
> 
> 
> 
> 
> --
> Kernelnewbies: Help each other learn about the Linux kernel.
> Archive:       http://mail.nl.linux.org/kernelnewbies/
> FAQ:           http://kernelnewbies.org/faq/
> 
>

--
Kernelnewbies: Help each other learn about the Linux kernel.
Archive:       http://mail.nl.linux.org/kernelnewbies/
FAQ:           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