Ejemplo n.º 1
0
    /* do remap by hand */
    virtad = &pgindex->buffer[ofs-intofs];
    vmf->page = virt_to_page(virtad); /* return page index */

    return 0;  /* everything went fine */ 
}

#else /* This is the old nopage method for compatibility reasons */
static struct page *dmar_vm_nopage(struct vm_area_struct * area, unsigned long address, int *nopage_type) {
    struct page *page = NOPAGE_SIGBUS; /* for debug, gives mempage */
    
    /* address relative to dma memory */
    unsigned long ofs = (address - area->vm_start) + VMA_OFFSET(area);
    unsigned long intofs;
    unsigned char * virtad = NULL; /* start ad of page in kernel space */
    struct dma_page_pointer *pgindex;
    
    /* find right page */
    pgindex = dma_main_pointer; /* start with first mem piece */
    intofs=0; /* linear offset of current mempiece start */
    while (intofs+pgindex->fullsize<=ofs) {
	intofs +=pgindex->fullsize;
	pgindex=pgindex->next;
	if (pgindex == dma_main_pointer) {
	    *nopage_type = VM_FAULT_SIGBUS; /* new in kernel 2.6 */
	    return NOPAGE_SIGBUS; /* ofs not mapped */
	}
    }; /* pgindex contains now the relevant page index */
    
    /* do remap by hand */
    virtad = &pgindex->buffer[ofs-intofs];  
    
    /* page table index */
    page=virt_to_page(virtad); 
    get_page(page); /* increment page use counter */
    *nopage_type = VM_FAULT_MINOR; /* new in kernel 2.6 */
    return page;
}
Ejemplo n.º 2
0
Archivo: mmap.c Proyecto: crond/dd
struct page *scullv_vma_nopage(struct vm_area_struct *vma,
                                unsigned long address, int write)
{
    unsigned long offset;
    ScullV_Dev *ptr, *dev = scullv_vma_to_dev(vma);
    struct page *page = NOPAGE_SIGBUS;
    void *pageptr = NULL; /* default to "missing" */
    pgd_t *pgd; pmd_t *pmd; pte_t *pte;
    unsigned long lpage;

    down(&dev->sem);
    offset = (address - vma->vm_start) + VMA_OFFSET(vma);
    if (offset >= dev->size) goto out; /* out of range */

    /*
     * Now retrieve the scullv device from the list,then the page.
     * If the device has holes, the process receives a SIGBUS when
     * accessing the hole.
     */
    offset >>= PAGE_SHIFT; /* offset is a number of pages */
    for (ptr = dev; ptr && offset >= dev->qset;) {
        ptr = ptr->next;
        offset -= dev->qset;
    }
    if (ptr && ptr->data) pageptr = ptr->data[offset];
    if (!pageptr) goto out; /* hole or end-of-file */

    /*
     * After scullv lookup, "page" is now the address of the page
     * needed by the current process. Since it's a vmalloc address,
     * first retrieve the unsigned long value to be looked up
     * in page tables.
     */
    lpage = VMALLOC_VMADDR(pageptr);
#ifdef LINUX_24						
    spin_lock(&init_mm.page_table_lock);
#endif  						
    pgd = pgd_offset(&init_mm, lpage);
    pmd = pmd_offset(pgd, lpage);
    pte = pte_offset(pmd, lpage);
#ifdef LINUX_24  					
    page = pte_page(*pte);
    spin_unlock(&init_mm.page_table_lock);
#else  							
    page = mem_map + MAP_NR(pte_page(*pte));  		
#endif  						
    
    /* got it, now increment the count */
    get_page(page);
out:
    up(&dev->sem);
    return page;
}
Ejemplo n.º 3
0
Archivo: mmap.c Proyecto: crond/dd
int scullv_mmap(struct file *filp, struct vm_area_struct *vma)
{
    struct inode *inode = INODE_FROM_F(filp);

    if (VMA_OFFSET(vma) & (PAGE_SIZE-1))                
        return -ENXIO; /* need aligned offsets */	

    /* don't do anything here: "nopage" will fill the holes */
    vma->vm_ops = &scullv_vm_ops;
    vma->vm_flags |= VM_RESERVED;
#ifdef LINUX_24					
    vma->vm_private_data = scullv_devices + MINOR(inode->i_rdev);
#else						
    vma->vm_file = filp;			
#endif						
    scullv_vma_open(vma);
    return 0;
}
Ejemplo n.º 4
0
/* vm_operations, die das eigentliche mmap über die nopage-methode vornehmen */
static struct page *dmar_vm_nopage(struct vm_area_struct * area, unsigned long address, int write_access) {
  struct page *page = NOPAGE_SIGBUS; /* for debug, gives mempage */

  /* address relative to dma memory */
  unsigned long ofs = (address - area->vm_start) + VMA_OFFSET(area);
  unsigned long intofs;
  unsigned char * virtad = NULL; /* start ad of page in kernel space */
  struct dma_page_pointer *pgindex;
#ifdef bla_nopage
  void * pga; /* for tests */
#endif
  /* pgd_t *pgd; pmd_t *pmd; pte_t *pte;  for getting mapping to real bufs 
  unsigned long lpage; */

  /* find right page */
  pgindex = dma_main_pointer; /* start with first mem piece */
  intofs=0; /* linear offset of current mempiece start */
  while (intofs+pgindex->fullsize<=ofs) {
    intofs +=pgindex->fullsize;
    pgindex=pgindex->next;
    if (pgindex == dma_main_pointer) return NOPAGE_SIGBUS; /* ofs not mapped */
  }; /* pgindex contains now the relevant page index */
  
  /* do remap by hand */
  virtad = &pgindex->buffer[ofs-intofs];  
  
  /* virtad = dma_main_pointer->buffer;   for tests only */
 
  /* page table index */
  
  page=virt_to_page(virtad); 
  
  get_page(page); /* increment page use counter */
  
#ifdef bla_nopage
  pga = page_address(page); /* for tests */
  printk("nopage-Zugriff; adr=%x, phys=%x, page=%x\n ofs=%x, intofs=%x, pgindex=%x, virtad = %x, pga= %x\n",
	 (int)address, (int)pgindex->physbuf,(int)page,(int)ofs,
 (int)intofs,(int)pgindex, (int)virtad, (int) pga);
#endif

  return page;
}
Ejemplo n.º 5
0
Archivo: mmap.c Proyecto: crond/dd
    /* don't do anything here: "nopage" will fill the holes */
    vma->vm_ops = &scullv_vm_ops;
    vma->vm_flags |= VM_RESERVED;
#ifdef LINUX_24					
    vma->vm_private_data = scullv_devices + MINOR(inode->i_rdev);
#else						
    vma->vm_file = filp;			
#endif						
    scullv_vma_open(vma);
    return 0;
}

#else /* LINUX_20 */
int scullv_mmap(struct inode *inode, struct file *filp,
                struct vm_area_struct *vma)
{

    if (VMA_OFFSET(vma) & (PAGE_SIZE-1))
        return -ENXIO; /* need aligned offsets */

    /*
     * A pointer to init_mm is needed to access page tables
     */
    if (!init_mm_ptr)
        retrieve_init_mm_ptr();

    /* don't do anything here: "nopage" will fill the holes */
    vma->vm_ops = &scullv_vm_ops;
    vma->vm_inode = inode;
    inode->i_count++;
    scullv_vma_open(vma);
    return 0;
}