From mboxrd@z Thu Jan 1 00:00:00 1970 From: Wei Liu Subject: Re: mmap in PV xen-4.0.1 Date: Wed, 10 Aug 2011 17:12:56 +0800 Message-ID: <20110810091256.GA1537@limbo> References: Mime-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit Return-path: Content-Disposition: inline In-Reply-To: List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xensource.com Errors-To: xen-devel-bounces@lists.xensource.com To: Eric Camachat Cc: xen-devel@lists.xensource.com List-Id: xen-devel@lists.xenproject.org On Tue, Aug 09, 2011 at 11:29:51PM -0700, Eric Camachat wrote: > Hi, > > I have a problem to map kernel memory to userspace via /dev/mem. > The mmap() succeeded, but when I try to access it, the program will > hang forever (until press ctrl-c to terminate it). > > # memtest-user > memtest_vma_open: virt 0x7fbc90085000, phys 0x3eee8000 > paddr = 0x3eee8000 >  mem = 0x7fbc90089000 >  map = 0x7fbc90085000 > map[0]= 4c4c4c4c > map[1]= 4c4c4c4c > *** Hang here, it cannot (finish) access the memory mapped via /dev/mem *** > > My test source below, and it runs properly on HVM, VirtualBox, QEM and > physical machines. > What mistake I did? > > My kernel module look like this: > ================================================================================= [...snip...] > memtest_ioctl(struct inode *inode, struct file *file, unsigned int cmd, >               unsigned long arg) > { >        int ret = -ENOIOCTLCMD; >        phys_addr_t *paddr; >        unsigned long *vaddr; >        uint32_t *size; > >        switch(cmd) { >        case MEMTEST_DMA_SIZE: >                size = (uint32_t*)arg; >                *size = _size; Though your output shows that this assignment works, shouldn't this kind of direct assignment across kernel space and user land be avoided? It is bad practice to do direct assignment I think. copy_{from,to}_user should do the job. >                ret = 0; >                break; >        case MEMTEST_DMA_PADDR: >                paddr = (phys_addr_t*)arg; >                *paddr = _pbase; >                ret = 0; >                break; >        case MEMTEST_DMA_VADDR: >                vaddr = (unsigned long*)arg; >                *vaddr = _vbase; >                ret = 0; >                break; >        } >        return ret; > } > > [...snip...] > static struct file_operations memtest_fops = { >        .owner          = THIS_MODULE, >        .llseek         = no_llseek, >        .ioctl          = memtest_ioctl, My kernel doesn't have field called 'ioctl' in file_operations. So which kernel do you use? 2.6.18? I don't have old kernel at the moment so I can't help you much... >        .mmap           = memtest_mmap, > }; > > [...snip...] > static void __exit memtest_exit(void) > { >        if (_vbase != 0) >                free_page(_vbase); I suppose you should use free_pages here, since you use __get_free_pages when allocating. >        unregister_chrdev(MEMTEST_MAJOR, MEMTEST_NAME); > } > > > MODULE_LICENSE("GPL"); > > module_init(memtest_init); > module_exit(memtest_exit); > ================================================================================= > > Here is my user program: > > ================================================================================= > [...snip...] > if (map) > { > printf("map[0]= %x\n", map[0]); > printf("map[1]= %x\n", map[1]); This confuses me. You did write different values in _vbase[0], _vbase[1]. But the output '4C4C4C4C' shows that the value is 'L'. I just skimmed the output and the code. I don't run your code since I don't have a suitible environment at the moment... Wei.