Dwayne Dietrich

memory mapping flexbus peripherals

Discussion created by Dwayne Dietrich Employee on Apr 1, 2006
This message contains an entire topic ported from the WildRice - Coldfire forum.  Freescale has received the approval from the WildRice administrator on seeding the Freescale forum with messages.  The original message and all replies are in this single message. We have seeded this new forum with selected information that we expect will be of value as you search for answers to your questions.  Freescale assumes no responsibility whatsoever with respect to Posted Material.  For additional information, please see the Terms of Use - Message Boards and Community Forums.  Thank You and Enjoy the Forum!
 

Dec 14, 2005, 8:26 AM
Post #1 of 8 (79 views)
Copy Shortcut
 [ColdFire] memory mapping flexbus peripherals  Can't Post 
--------------------------------------------------------------------------------
 
Can anyone offer some help on the following problem. I'm using a 5472
with the 2.6.10 kernel. I have some peripherals on flex bus that I want
to access from user space. I have set up the flex bus registers to put
the peripherals at a base address of 0xBB000000. I have written a
driver that implements mmap. Here is the relevant code from the driver:
#define FLEXBUS_CS5_BASE_ADDR 0xBB000000
#define FLEXBUS_CS5_SIZE 8192
static int flexbus_mmap(struct file *filep, struct vm_area_struct *vma)
{
unsigned long size = vma->vm_end - vma->vm_start;
unsigned long addr = FLEXBUS_CS5_BASE_ADDR >> PAGE_SHIFT;
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
if (remap_pfn_range(vma, vma->vm_start, addr, size,
vma->vm_page_prot))
{
return -EAGAIN;
}
vma->vm_ops = &flexbus_vm_ops;
flexbus_vma_open(vma);
return 0;
}
>From userspace, I successfully open and mmap the device, but when I
access the memory, I get a segmentation fault. Here's what I'm doing
from userspace.
int fd;
unsigned long *mem;
fd = open("/dev/flexbus", O_RDWR);
if (!fd) exit(-1);
mem = mmap(0, FLEXBUS_CS5_SIZE, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
if (mem == MAP_FAILED) exit(-1);
mem[0x402] = 0xdecafbad;
munmap(mem, FLEXBUS_CS5_SIZE);
close(fd);
return 0;
The segfault happens on the mem[0x402] = ... line. Any ideas what I'm
doing wrong?
Thanks,
Steve

--------------------------------------------------------------------
Dec 14, 2005, 2:58 PM
Post #2 of 8 (79 views)
Copy Shortcut
 Re: [ColdFire] memory mapping flexbus peripherals [In reply to]  Can't Post 
--------------------------------------------------------------------------------
 
In the interest of simplifying things, I wrote a simpler program that
demonstrates the same problem. This is a userspace program that calls
mmap on /dev/mem to map the desired flexbus addresses into user space.
What's interesting is that I can read from the mmap'ed region, but when
I write to it, I get a segfault. Any ideas?
#include <fcntl.h>
#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
#define MMAP_PHYS_BASE 0xBB000000
#define MMAP_SIZE 8192
int main(int argc, char *argv[])
{
int fd;
unsigned long *virt_addr;
char *dev = "/dev/mem";
if (!(fd = open(dev, O_RDWR)))
{
printf("failed opening %s\n", dev);
return -1;
}
virt_addr = mmap(0, MMAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
fd, MMAP_PHYS_BASE);
if (virt_addr == MAP_FAILED)
{
printf("mmap failed\n");
return -1;
}
printf("virt_addr[1] = 0x%0lx\n", virt_addr[1]);
fflush(stdout);
virt_addr[1] = 0xdecafbad;
printf("virt_addr[1] = 0x%0lx\n", virt_addr[1]);
fflush(stdout);
if (munmap(virt_addr, MMAP_SIZE) != 0)
{
printf("munmap failed\n");
}
close(fd);
return 0;
}
On Wed, 2005-12-14 at 11:26 -0500, Steve Joiner wrote:
> Can anyone offer some help on the following problem. I'm using a 5472
> with the 2.6.10 kernel. I have some peripherals on flex bus that I want
> to access from user space. I have set up the flex bus registers to put
> the peripherals at a base address of 0xBB000000. I have written a
> driver that implements mmap. Here is the relevant code from the driver:
>
> #define FLEXBUS_CS5_BASE_ADDR 0xBB000000
> #define FLEXBUS_CS5_SIZE 8192
>
> static int flexbus_mmap(struct file *filep, struct vm_area_struct *vma)
> {
> unsigned long size = vma->vm_end - vma->vm_start;
> unsigned long addr = FLEXBUS_CS5_BASE_ADDR >> PAGE_SHIFT;
>
> vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
>
> if (remap_pfn_range(vma, vma->vm_start, addr, size,
> vma->vm_page_prot))
> {
> return -EAGAIN;
> }
>
> vma->vm_ops = &flexbus_vm_ops;
> flexbus_vma_open(vma);
> return 0;
> }
>
> >From userspace, I successfully open and mmap the device, but when I
> access the memory, I get a segmentation fault. Here's what I'm doing
> from userspace.
>
> int fd;
> unsigned long *mem;
>
> fd = open("/dev/flexbus", O_RDWR);
> if (!fd) exit(-1);
>
> mem = mmap(0, FLEXBUS_CS5_SIZE, PROT_READ | PROT_WRITE,
> MAP_SHARED, fd, 0);
> if (mem == MAP_FAILED) exit(-1);
>
> mem[0x402] = 0xdecafbad;
>
> munmap(mem, FLEXBUS_CS5_SIZE);
> close(fd);
> return 0;
>
> The segfault happens on the mem[0x402] = ... line. Any ideas what I'm
> doing wrong?
>
> Thanks,
> Steve
>
>
--------------------------------------------------------------------
Dec 14, 2005, 3:31 PM
Post #3 of 8 (78 views)
Copy Shortcut
 Re: [ColdFire] memory mapping flexbus peripherals [In reply to]  Can't Post 
--------------------------------------------------------------------------------
 
 
>In the interest of simplifying things, I wrote a simpler program that
>demonstrates the same problem. This is a userspace program that calls
>mmap on /dev/mem to map the desired flexbus addresses into user space.
>What's interesting is that I can read from the mmap'ed region, but when
>I write to it, I get a segfault. Any ideas?
Yup.
Which LinuxBSP are you using?
I've found problems in this area where if its written first it works
fine, but if read first, SIGSEGV shows up on the first write.
The problem stems from the fault handler trying to setup up a shared
mapping to be a copy-on-write(COW), and bails when it does this for the IO
mmap'd space.
The trick is to modify the definitions of _S001, _S011 in
linux-2.4.26/include/asm/cf_pagetable.h to also include the dirty bits
so the page table entry(PTE) contains the dirty bit to start with
which prevents the fault handler from removing the write permission in
an effort to trigger the TLB code from trying to COW.
--
Peter Barada

--------------------------------------------------------------------
Dec 14, 2005, 4:51 PM
Post #4 of 8 (78 views)
Copy Shortcut
 Re: [ColdFire] memory mapping flexbus peripherals [In reply to]  Can't Post 
--------------------------------------------------------------------------------
 
On Wed, 2005-12-14 at 18:31 -0500, Peter Barada wrote:
> >In the interest of simplifying things, I wrote a simpler program that
> >demonstrates the same problem. This is a userspace program that calls
> >mmap on /dev/mem to map the desired flexbus addresses into user space.
> >What's interesting is that I can read from the mmap'ed region, but when
> >I write to it, I get a segfault. Any ideas?
>
> Yup.
>
> Which LinuxBSP are you using?
Ltib, dated 20050802 with the 2.6.10 kernel.
> I've found problems in this area where if its written first it works
> fine, but if read first, SIGSEGV shows up on the first write.
I tried writing first, but it still segfaulted.
> The problem stems from the fault handler trying to setup up a shared
> mapping to be a copy-on-write(COW), and bails when it does this for the IO
> mmap'd space.
>
> The trick is to modify the definitions of _S001, _S011 in
> linux-2.4.26/include/asm/cf_pagetable.h to also include the dirty bits
> so the page table entry(PTE) contains the dirty bit to start with
> which prevents the fault handler from removing the write permission in
> an effort to trigger the TLB code from trying to COW.
I made the modifications you suggested, but the behavior was still the
same. Any other ideas?
Here's the relevant part of my linux-2.6.10/include/asm/cf_pagetable.h
after my modifications to add the dirty bits to _S001 and _S011.
#define __S000 PAGE_NONE
#define __S100 __pgprot(CF_PAGE_VALID \
| CF_PAGE_ACCESSED \
| CF_PAGE_SHARED \
| CF_PAGE_EXEC)
#define __S010 PAGE_SHARED
#define __S110 __pgprot(CF_PAGE_VALID \
| CF_PAGE_ACCESSED \
| CF_PAGE_SHARED \
| CF_PAGE_EXEC)
#define __S001 __pgprot(CF_PAGE_VALID \
| CF_PAGE_ACCESSED \
| CF_PAGE_SHARED \
| CF_PAGE_DIRTY \
| CF_PAGE_READABLE)
#define __S101 __pgprot(CF_PAGE_VALID \
| CF_PAGE_ACCESSED \
| CF_PAGE_SHARED \
| CF_PAGE_READABLE \
| CF_PAGE_EXEC)
#define __S011 __pgprot(CF_PAGE_VALID \
| CF_PAGE_ACCESSED \
| CF_PAGE_SHARED \
| CF_PAGE_DIRTY \
| CF_PAGE_READABLE)
#define __S111 __pgprot(CF_PAGE_VALID \
| CF_PAGE_ACCESSED \
| CF_PAGE_SHARED \
| CF_PAGE_READABLE \
| CF_PAGE_EXEC)
-Steve

--------------------------------------------------------------------
Dec 14, 2005, 6:53 PM
Post #5 of 8 (77 views)
Copy Shortcut
 Re: [ColdFire] memory mapping flexbus peripherals [In reply to]  Can't Post 
--------------------------------------------------------------------------------
 
 
>> >In the interest of simplifying things, I wrote a simpler program that
>> >demonstrates the same problem. This is a userspace program that calls
>> >mmap on /dev/mem to map the desired flexbus addresses into user space.
>> >What's interesting is that I can read from the mmap'ed region, but when
>> >I write to it, I get a segfault. Any ideas?
>>
>> Yup.
>>
>> Which LinuxBSP are you using?
>
>Ltib, dated 20050802 with the 2.6.10 kernel.
I'm running the Logic 2.4.26 kernel.
>> I've found problems in this area where if its written first it works
>> fine, but if read first, SIGSEGV shows up on the first write.
>
>I tried writing first, but it still segfaulted.
>
>> The problem stems from the fault handler trying to setup up a shared
>> mapping to be a copy-on-write(COW), and bails when it does this for the IO
>> mmap'd space.
>>
>> The trick is to modify the definitions of _S001, _S011 in
>> linux-2.4.26/include/asm/cf_pagetable.h to also include the dirty bits
>> so the page table entry(PTE) contains the dirty bit to start with
>> which prevents the fault handler from removing the write permission in
>> an effort to trigger the TLB code from trying to COW.
>
>I made the modifications you suggested, but the behavior was still the
>same. Any other ideas?
>
>Here's the relevant part of my linux-2.6.10/include/asm/cf_pagetable.h
>after my modifications to add the dirty bits to _S001 and _S011.
Hmm, they look good. I'll have a go with your test program and see
what I get on the Logic 2.4.26 kernel...
--
Peter Barada

--------------------------------------------------------------------
Dec 14, 2005, 10:10 PM
Post #6 of 8 (75 views)
Copy Shortcut
 Re: [ColdFire] memory mapping flexbus peripherals [In reply to]  Can't Post 
--------------------------------------------------------------------------------
 
Steve Joiner wrote:
>On Wed, 2005-12-14 at 18:31 -0500, Peter Barada wrote:
>
>
>>>In the interest of simplifying things, I wrote a simpler program that
>>>demonstrates the same problem. This is a userspace program that calls
>>>mmap on /dev/mem to map the desired flexbus addresses into user space.
>>>What's interesting is that I can read from the mmap'ed region, but when
>>>I write to it, I get a segfault. Any ideas?
>>>
>>>
>>Yup.
>>
>>Which LinuxBSP are you using?
>>
>>
>
>Ltib, dated 20050802 with the 2.6.10 kernel.
>
>
>
>>I've found problems in this area where if its written first it works
>>fine, but if read first, SIGSEGV shows up on the first write.
>>
>>
>
>I tried writing first, but it still segfaulted.
>
>
>
>>The problem stems from the fault handler trying to setup up a shared
>>mapping to be a copy-on-write(COW), and bails when it does this for the IO
>>mmap'd space.
>>
>>The trick is to modify the definitions of _S001, _S011 in
>>linux-2.4.26/include/asm/cf_pagetable.h to also include the dirty bits
>>so the page table entry(PTE) contains the dirty bit to start with
>>which prevents the fault handler from removing the write permission in
>>an effort to trigger the TLB code from trying to COW.
>>
>>
>
>I made the modifications you suggested, but the behavior was still the
>same. Any other ideas?
>
>Here's the relevant part of my linux-2.6.10/include/asm/cf_pagetable.h
>after my modifications to add the dirty bits to _S001 and _S011.
>
>#define __S000 PAGE_NONE
>#define __S100 __pgprot(CF_PAGE_VALID \
> | CF_PAGE_ACCESSED \
> | CF_PAGE_SHARED \
> | CF_PAGE_EXEC)
>#define __S010 PAGE_SHARED
>#define __S110 __pgprot(CF_PAGE_VALID \
> | CF_PAGE_ACCESSED \
> | CF_PAGE_SHARED \
> | CF_PAGE_EXEC)
>#define __S001 __pgprot(CF_PAGE_VALID \
> | CF_PAGE_ACCESSED \
> | CF_PAGE_SHARED \
> | CF_PAGE_DIRTY \
> | CF_PAGE_READABLE)
>#define __S101 __pgprot(CF_PAGE_VALID \
> | CF_PAGE_ACCESSED \
> | CF_PAGE_SHARED \
> | CF_PAGE_READABLE \
> | CF_PAGE_EXEC)
>#define __S011 __pgprot(CF_PAGE_VALID \
> | CF_PAGE_ACCESSED \
> | CF_PAGE_SHARED \
> | CF_PAGE_DIRTY \
> | CF_PAGE_READABLE)
>#define __S111 __pgprot(CF_PAGE_VALID \
> | CF_PAGE_ACCESSED \
> | CF_PAGE_SHARED \
> | CF_PAGE_READABLE \
> | CF_PAGE_EXEC)
>
>-Steve
>
Maybe, the problem is there because of the mapped readonly pages
Try add a WRITABLE flag will make all work, I think.
BR!
Leo Liu
--------------------------------------------------------------------
Dec 15, 2005, 6:58 AM
Post #7 of 8 (75 views)
Copy Shortcut
 Re: [ColdFire] memory mapping flexbus peripherals [In reply to]  Can't Post 
--------------------------------------------------------------------------------
 
 
>Maybe, the problem is there because of the mapped readonly pages
>Try add a WRITABLE flag will make all work, I think.
Yup. That should do it, along with the DIRTY bit, at least for the
writable shared pages...
--
Peter Barada
--------------------------------------------------------------------
Dec 15, 2005, 8:22 AM
Post #8 of 8 (75 views)
Copy Shortcut
 Re: [ColdFire] memory mapping flexbus peripherals [In reply to]  Can't Post 
--------------------------------------------------------------------------------
 
Adding the WRITABLE and DIRTY flags did the trick. Peter and Leo,
thanks very much for the help.
-Steve
On Thu, 2005-12-15 at 09:58 -0500, Peter Barada wrote:
> >Maybe, the problem is there because of the mapped readonly pages
> >Try add a WRITABLE flag will make all work, I think.
>
> Yup. That should do it, along with the DIRTY bit, at least for the
> writable shared pages...
>
 
 
 

Message Edited by Dietrich on 04-03-2006 10:47 AM

Message Edited by Dietrich on 04-04-2006 09:06 PM

Outcomes