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/