RE: identify a vitual address
Eli Cohen <eli-VPRAkNaXOzVS1MOuV/[email protected]>
| Newsgroups | gmane.linux.redhat.taroon |
|---|---|
| Message-ID | <[email protected]> |
Attached the implementation for AS 2.1
/*
* Translate a virtual address to physical address
*
*/
MT_phys_addr_t MOSAL_virt_to_phys_ex(const MT_virt_addr_t va, struct page
**page_pp)
{
pgd_t *pgd;
pmd_t *pmd;
pte_t *pte;
mem_map_t * page;
MT_phys_addr_t pa;
spinlock_t *page_table_lock_p;
pte_t *pte_b;
if ( in_interrupt() ) {
MTL_ERROR1(MT_FLFMT("%s: called in interrupt"), __func__);
return INVAL_PHYS_ADDR;
}
/* advanced server 2.1 implementation */
if ( va < PAGE_OFFSET ) {
page_table_lock_p = ¤t->mm->page_table_lock;
spin_lock(page_table_lock_p);
pgd = pgd_offset(current->mm, va);
if (pgd_none(*pgd) || pgd_bad(*pgd)) {
spin_unlock(page_table_lock_p);
MTL_ERROR1(MT_FLFMT("bad pgd"));
return INVAL_PHYS_ADDR;
}
}
else if ( va<(MT_virt_addr_t)high_memory ) {
MTL_TRACE7(MT_FLFMT("kernel logical memory: va=0x"VIRT_ADDR_FMT",
virt_to_phys(va)=0x%lx"), va, virt_to_phys((void *)va));
if ( page_pp ) *page_pp = &mem_map[(va-PAGE_OFFSET)>>PAGE_SHIFT];
return virt_to_phys((void *)va);
}
else {
page_table_lock_p = &init_mm.page_table_lock;
spin_lock(page_table_lock_p);
pgd = pgd_offset_k(va);
}
pmd = pmd_offset(pgd, va);
if (pmd_bigpage(*pmd)) {
MTL_TRACE7(MT_FLFMT("Big page !!!"));
page = pmd_page(*pmd) + (va & BIGPAGE_MASK) / PAGE_SIZE;
}
else {
if (pmd_none(*pmd) || pmd_bad(*pmd)) {
spin_unlock(page_table_lock_p);
MTL_ERROR1(MT_FLFMT("bad pmd: va="VIRT_ADDR_FMT), va);
return INVAL_PHYS_ADDR;
}
spin_unlock(page_table_lock_p); /* free the lock since kmap may block */
pte_b = kmap(mem_map+(pmd_val(*pmd)>>PAGE_SHIFT));
spin_lock(page_table_lock_p);
if (!pte_b) {
spin_unlock(page_table_lock_p);
MTL_ERROR1(MT_FLFMT("%s: failed to map page table: va="VIRT_ADDR_FMT),
__func__, va);
return INVAL_PHYS_ADDR;
}
pte = pte_b + __pte_offset(va);
if ( !pte_present(*pte) ) {
spin_unlock(page_table_lock_p);
MTL_ERROR1(MT_FLFMT("pte points to a non present page frame !!!:
va="VIRT_ADDR_FMT), va);
kunmap(mem_map+(pmd_val(*pmd)>>PAGE_SHIFT));
return INVAL_PHYS_ADDR;
}
page = pte_page(*pte);
kunmap(mem_map+(pmd_val(*pmd)>>PAGE_SHIFT));
}
spin_unlock(page_table_lock_p);
if(!VALID_PAGE(page))
{
MTL_ERROR4("%s: invalid memory address va="VIRT_ADDR_FMT"\n",
__func__, va);
return INVAL_PHYS_ADDR;
}
MTL_TRACE4("%s: page address=%p\n", __func__, page);
if ( page_pp ) *page_pp = page;
pa = ((MT_phys_addr_t)(page - mem_map) << PAGE_SHIFT) | (va & (PAGE_SIZE -
1));
MTL_TRACE4("%s: va="VIRT_ADDR_FMT", pa="PHYS_ADDR_FMT"\n", __func__, va,
pa);
return pa;
}
-----Original Message-----
From: Arjan van de Ven [mailto:[email protected]]
Sent: Tuesday, September 16, 2003 12:23 PM
To: [email protected]
Subject: Re: identify a vitual address
On Tue, 2003-09-16 at 11:10, Eli Cohen wrote:
> Hi,
> I have to implement a function that returns the physical address given
> the virtual address. I use a method similar to follow_page()
> implementation.
can you post a pointer to the source of your module? That way it's more
obvious why you're trying to do what you do...,