-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hi! I'm writing a kernel module that allocates 4 Mb of kernel memory which is mmap'd by a daemon via a character device. For the mmap implementation, I have a vm_operations_struct.nopage handler routine: /** * sahn_vm_nopage - 'nopage' vm handler, maps shared memory * @vma: vma struct * @vaddr: virtual address that caused fault * @type: output-only param, type of fault */ static struct page* sahn_vm_nopage(struct vm_area_struct *vma, unsigned long vaddr, int *type) { struct page *page; struct sahn_priv *priv = (struct sahn_priv*) vma->vm_private_data; unsigned long physaddr, pageframe; if ( priv == NULL ) return NOPAGE_OOM; if ( vaddr > vma->vm_end ) return NOPAGE_SIGBUS; physaddr = (vaddr - vma->vm_start) + virt_to_phys(priv->shared); pageframe = physaddr >> PAGE_SHIFT; page = pfn_to_page(pageframe); SAHNDP(1, "In sahn_vm_nopage; mapping physaddr %x, pageframe %x\n", (unsigned int) physaddr, (unsigned int) pageframe); get_page(page); if ( type ) *type = VM_FAULT_MINOR; return page; } And here's the mmap routine: /** * sahn_char_mmap - map shared memory * @filp file struct * @vma vma area struct */ int sahn_char_mmap(struct file* filp, struct vm_area_struct *vma) { unsigned long start = vma->vm_start; unsigned long size = vma->vm_end - start; int id = iminor(filp->f_dentry->d_inode); struct net_device* dev = sahn_get_sahndevice(id); struct sahn_priv* priv; unsigned long pagesize, origsize; if ( !dev ) { SAHNERRP("Couldn't find device while trying to mmap()!\n"); return -EINVAL; } // Make sure mmap requests reading and writing if ( !(vma->vm_flags & (VM_WRITE | VM_READ)) ) { SAHNERRP("Undefined mmap() access.\n"); return -EINVAL; } // Verify requested size is = size of shared area origsize = sizeof(struct sahn_shared); for ( pagesize=PAGE_SIZE; pagesize < origsize; pagesize <<= 1 ); if ( size > pagesize ) { SAHNERRP("Requested mmap() size out of range.\n"); return -EINVAL; } SAHNDP(3, "Configuring mmap() system for device %s (to user addr. %p)\n", dev->name, (void*) start); priv = netdev_priv(dev); priv->user_offset = start; vma->vm_flags |= VM_RESERVED; vma->vm_ops = &sahn_vm_ops; vma->vm_private_data = priv; return 0; } All works well if I only access memory (from the daemon) in the first page of the shared area. But if I go over that boundary, and access any other page than the first, I get kernel panics, which ultimately kill the system. Here's a sequence of screen captures: http://mike.tyson.id.au/panics (That's the best capture speed I could get; skips some information) Runs like: // Map memory shared = (struct sahn_shared*) mmap(0, sizeof(struct sahn_shared), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); int i, tmp; for ( i=0; i<10; i++ ) { tmp = ((char*) shared)[i]; ((char*) shared)[i]++; ((char*) shared)[i]--; } .. Work fine, whereas if I change the end condition for that for loop from 10 to, say 16000, the machine crashes after one to three runs. (Note that it doesn't always happen on the first run.. Sometimes takes up to three) What am I doing wrong here? Cheers =) Mike - -- Mike Tyson <mike@xxxxxxxxxxx> M: (+61) 0407 754 124 W: http://mike.tyson.id.au B: http://mike.tyson.id.au/blog -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.1 (GNU/Linux) iD8DBQFDTKQs/eih+gEb7pQRAkiuAKCbN34I1hGiQeqB9PFryRmNs8N8YwCgqhOQ lM6al1n3l+wgKzPNhXuMofs= =4CCW -----END PGP SIGNATURE----- -- Kernelnewbies: Help each other learn about the Linux kernel. Archive: http://mail.nl.linux.org/kernelnewbies/ FAQ: http://kernelnewbies.org/faq/