LinuxQuestions.org
Help answer threads with 0 replies.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Software > Linux - Kernel
User Name
Password
Linux - Kernel This forum is for all discussion relating to the Linux kernel.

Notices


Reply
  Search this Thread
Old 07-10-2011, 10:30 AM   #1
spong
LQ Newbie
 
Registered: Jul 2011
Posts: 3

Rep: Reputation: Disabled
copy_from_user strangeness


I'm having problems using copy_from_user to copy a buffer passed to an IOCTL to device physical memory. The copy appears to work (returns 0), but the memory doesn't actually get written. If I use memset, or use copy_from_user to a different kernel space buffer, and then memcpy to the physical memory, it works fine. Similarly I can READ into the user space buffer just fine using copy_to_user. Should I not be expecting copy_from_user to be able to write to a kernel virtual address that was mapped to physical device space?

Here's some code.

I initialize my pointer during PCI probe as such, the test code at the end is just to initialize the memory to indentifiable values that i can later dump:
drv_data->length = pci_resource_len(pdev,0);

drv_data->virtual_address = ioremap_nocache(drv_data->physical_address,drv_data->length);
if(drv_data->virtual_address == NULL) {
printk(KERN_ERR "%s ERROR: Could not remap BAR0(0x%#lX,%ld bytes).\n",
DRV_NAME,drv_data->physical_address, drv_data->length);
return -ENOMEM;
}

if(request_mem_region(drv_data->physical_address, drv_data->length, drv_data->device_name)==NULL) {
printk(KERN_ERR "%s ERROR: Memory range %#lX-%#lX could not be allocated.\n",
DRV_NAME,drv_data->physical_address,drv_data->physical_address+drv_data->length-1);
return -EBUSY;
}

/*Test Code*/
ptr = drv_data->virtual_address;
for(i=0;i<1024*1024;i++) {
*ptr++=i;
}

ptr = drv_data->virtual_address;
for(i=0;i<1024*1024;i++) {
if(i%16 ==0 && i!=0) printk("\n");
printk("%.2X ",*ptr++);
}


The IOCTL write from user space to device physical space is done via:
err = !access_ok(VERIFY_READ, (void __user *)arg, sizeof(struct pci_data));
if(err) return -EFAULT;
udata = (struct pci_data *)arg;
get_user(offset,&udata->addr);
if(offset+64 >= drv_data->length)
return -EFAULT;
kmem = drv_data->virtual_address;
kmem += offset;

//memset(dummy,0,64); //If i replace dummy with kmem, this works
notcopied=copy_from_user(kmem, udata->data, 64); //returns 0, memory not set
//memcpy(kmem,dummy,64); //if I replace kmem with dummy in copy_from_user above, this works
printk("%s Wrote %.2X to %#lX (%#lX), didn't copy %d bytes (%.16lX, %.16lX, %.16lX).\n",DRV_NAME,t,offset,(unsigned long)kmem,notcopied,udata->data, &udata->data, &udata->data[0]);
ret = 0;
break;



Then I read the data out with this ioctl command: (This code works as I expect)
err = !access_ok(VERIFY_WRITE, (void __user *)arg, sizeof(struct pci_data));
if(err) return -EFAULT;
udata = (struct pci_data *)arg;
get_user(offset,&udata->addr);
if(offset+64 >= drv_data->length)
return -EFAULT;
kmem = drv_data->virtual_address;
kmem += offset;
notcopied=copy_to_user(udata->data, kmem, 64);
printk("%s Reading 64 bytes from %#lx (%#lX), first value %.2X. Didn't copy %d bytes.\n",DRV_NAME,offset,(unsigned long)kmem,*kmem,notcopied);
ret = 0;
break;
 
Old 07-11-2011, 12:49 AM   #2
bsat
Member
 
Registered: Feb 2009
Posts: 347

Rep: Reputation: 72
What memory does "dummy" point to ?
 
Old 07-11-2011, 05:51 PM   #3
spong
LQ Newbie
 
Registered: Jul 2011
Posts: 3

Original Poster
Rep: Reputation: Disabled
Dummy is kernel memory, declared in my IOCTL function as char dummy[64];

Other useful information may be uname -a:
Linux dev 2.6.38-8-generic #42-Ubuntu SMP Mon Apr 11 03:31:24 UTC 2011 x86_64 x86_64 x86_64 GNU/Linux

Everything I've read suggests that I absolutely should not use the pointer returned from ioremap as a pointer because it is not portable (some systems don't allow direct memory access of I/O devices), but it should work on x86.
 
Old 07-11-2011, 11:58 PM   #4
bsat
Member
 
Registered: Feb 2009
Posts: 347

Rep: Reputation: 72
have you done a kmalloc for dummy before using memset on it. I am not sure, but if you have not, it might lead to problems.
 
Old 07-12-2011, 09:40 AM   #5
spong
LQ Newbie
 
Registered: Jul 2011
Posts: 3

Original Poster
Rep: Reputation: Disabled
Well no, the dummy is allocated on the stack which is in kernel space, I don't really need to do a kmalloc for that and it works fine.

When I do the copy from user to dummy (kernel space, declared on the stack), and from dummy to the physical PCI device (ioremapped to kernel space virtual address), it works fine. When I copy directly from user space to the PCI device (even though the PCI device virtual address is mapped into kernel memory), copy_from_user returns 0 (success) but does not actually perform the copy.
 
Old 02-10-2014, 05:01 AM   #6
jmhmcg
LQ Newbie
 
Registered: Feb 2014
Distribution: Gentoo
Posts: 5

Rep: Reputation: Disabled
Have you found any further details on this? I spotted this post: http://www.linuxquestions.org/questi...module-455036/
 
Old 02-10-2014, 09:06 AM   #7
jmhmcg
LQ Newbie
 
Registered: Feb 2014
Distribution: Gentoo
Posts: 5

Rep: Reputation: Disabled
I also spotted copy_from_user_toio: http://pl.digipedia.org/man/doc/view...m_user_toio.9/ and http://kerneldox.com/kdox-linux/d7/d...c6e492575d836a here too.

Last edited by jmhmcg; 02-11-2014 at 05:06 AM. Reason: Added another link.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
copy_from_user() function fails inside a kernel thread. rajneesh.gaur Linux - Newbie 1 02-18-2012 04:58 PM
Using copy_from_user with 2 process wk30l Programming 1 10-25-2010 02:09 PM
copy_from_user and copy_to_user example krisonearth Programming 5 09-29-2009 05:08 PM
copy_from_user does not copy from process-heap najoshi Linux - Kernel 0 08-16-2009 12:09 AM
internet strangeness slackwarefan Slackware 2 11-29-2005 10:16 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Software > Linux - Kernel

All times are GMT -5. The time now is 02:23 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration