Linux r1 2.4.21-27.ELsmp #1 SMP Wed Dec 1 21:59:02 EST 2004 i686 i686 i386 GNU/Linux
I wrote a kernel module. It use vma nopage handle to mmap vmallocated memroy to userspace.
It converts kernel virtual address returned by vmalloc() to page struct by vmalloc_to_page().
It works well the first time I insmod it , then I remove it by rmmod.
When reinsmod it ,and use my user space app to mmap and access shared memory.
kernel panic occurs.
The following is my vma nopage handler.
struct page* vma_nopage(struct vm_area_struct *vma, unsigned long address, int write_access)
{
unsigned long offset;
struct page* page_ptr;
offset = address - vma->vm_start + (vma->vm_pgoff<<PAGE_SHIFT);
/* caculate the page ptr */
page_ptr = mmapdrv_vmalloc_to_page((void*)((unsigned long)vmalloc_area + offset));
/* we didn't find the page in page table*/
if(0ul == (unsigned long)page_ptr)
{
return ((struct page*)0);
printk("mmap_drv: page fault. didn't find page\n";
}else
{
atomic_inc(&(page_ptr->count));
}
return ((struct page*)page_ptr);
}
struct page * vmalloc_to_page(void * vmalloc_addr)
{
unsigned long addr = (unsigned long) vmalloc_addr;
struct page *page = NULL;
pmd_t *pmd;
pte_t *pte;
pgd_t *pgd;
pgd = pgd_offset_k(addr);
if (!pgd_none(*pgd)) {
pmd = pmd_offset(pgd, addr);
if (!pmd_none(*pmd)) {
/* FIXME: shouldn't this be pte_offset_kernel ??? */
pte = pte_offset_map(pmd, addr);
if (pte_present(*pte)) {
page = pte_page(*pte);
}
pte_unmap(pte);
~~~~~~~~~~~~~~ what's the usage of this function?
}
}
return page;
}
I have tried to remove the red line atomic_inc(&(page_ptr->count)
or remove pte_unmap(pte) in vmalloc_to_page(),
I works normally.
Who can tell me what's the mystery in it?
--
trulyliu@xxxxxxxxx