* mmap + segfaults on MPC8349E
@ 2007-12-09 2:44 R. Ebersole (VTI - new)
2007-12-09 4:01 ` David Hawkins
0 siblings, 1 reply; 6+ messages in thread
From: R. Ebersole (VTI - new) @ 2007-12-09 2:44 UTC (permalink / raw)
To: linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 1462 bytes --]
Hi.
We've run into an .... interesting (and frustrating) occurance recently
while testing
out a new board (and BSP). We were wondering if anybody has seen anything
like this.
A description follows:
We wrote some simple drivers/modules to mmap() FPGA registers to user space.
At the moment, for testing, we reserve the upper x-MB of RAM, and mmap()
there, instead.
We open 4 such devices, and mmap() 64KB of space (memory, in this case)
for each.
Accessing the first device opened & mmapped was fine. But accesssing
the 2nd device
yielded some odd behavior. We could read and write the first and 3rd 4K
regions fine, but
if we read from the 2nd one (at offset 0x1000) before we wrote to it, we
get a segmentation
fault. If, however, we wrote first (to the 2nd region), then things
were OK.
Addendum: With the real device, this same behavior happens at the 10th
4-KB region of the device.
Without any of the others mmap()-ed. If we mmap() just that 4-KB
region, things are fine. We
can access the region with ioremap() in the driver w/o issues.
We are running on an MPC8349-E.
Any thoughts or ideas?
vti
--
This message contains confidential information and is intended only for the
individual named. If you are not the intended recipient you should not
disseminate, distribute or copy this e-mail. Please notify the sender
immediately by e-mail if you have received this e-mail by mistake and delete
this e-mail from your system.
[-- Attachment #2: Type: text/html, Size: 1987 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: mmap + segfaults on MPC8349E
2007-12-09 2:44 mmap + segfaults on MPC8349E R. Ebersole (VTI - new)
@ 2007-12-09 4:01 ` David Hawkins
2007-12-11 1:53 ` R. Ebersole (VTI - new)
0 siblings, 1 reply; 6+ messages in thread
From: David Hawkins @ 2007-12-09 4:01 UTC (permalink / raw)
To: R. Ebersole (VTI - new); +Cc: linuxppc-embedded
Hi,
You haven't really provided enough information.
> We wrote some simple drivers/modules to mmap() FPGA registers to user space.
> At the moment, for testing, we reserve the upper x-MB of RAM, and mmap()
> there, instead.
1. The FPGA is located where? The local bus, or the PCI bus?
What frequency are you trying to operate at?
2. If its on the local bus, do you access it using GPCM or UPM?
Have you setup either correctly?
Have you confirmed the bus timing with a logic analyzer?
3. Have you created a bus functional model of the processor bus
that you have then run with your FPGA bus in ModelSim to
confirm that your FPGA performs correctly.
4. Have you tried burst and non-burst access by either using
DMA, or treating the memory area as cacheable or non-cacheable?
Have you checked those cases with simulation and then
with a scope or logic analyzer?
5. Did you try running stand-alone tests in U-Boot, to go for a
more bare-metal debug approach?
No point in debugging software if you have no idea whether the
hardware behaves. So confirm that you have tested your hardware
first.
My board design uses the MPC8349EA, I have an Altera Stratix II
FPGA on the local bus. I use GPCM to access flash on the local
bus via the FPGA, and UPM to access FPGA registers. I don't
have boards yet, but I've got a pretty good handle on how the
interface should work.
Cheers,
Dave
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: mmap + segfaults on MPC8349E
2007-12-09 4:01 ` David Hawkins
@ 2007-12-11 1:53 ` R. Ebersole (VTI - new)
2007-12-11 2:16 ` David Hawkins
0 siblings, 1 reply; 6+ messages in thread
From: R. Ebersole (VTI - new) @ 2007-12-11 1:53 UTC (permalink / raw)
To: David Hawkins; +Cc: linuxppc-embedded
David Hawkins wrote:
> Hi,
Hi.
>
> You haven't really provided enough information.
Sorry about that. I grabbed one of the h/w guys to help out.
>
>> We wrote some simple drivers/modules to mmap() FPGA registers to user
>> space.
>> At the moment, for testing, we reserve the upper x-MB of RAM, and
>> mmap() there, instead.
>
>
> 1. The FPGA is located where? The local bus, or the PCI bus?
> What frequency are you trying to operate at?
On the local bus frequency is 33.0 MHz. (66.0 PCI_CLK_IN). See the
attached .cfg script for memory map.
>
>
> 2. If its on the local bus, do you access it using GPCM or UPM?
> Have you setup either correctly?
> Have you confirmed the bus timing with a logic analyzer?
GPCM.
We have confirmed the timing both in functionality (in the debugger) and
with a logic analyzer (plus oscope for setup and hold times).
We have stand-alone C-code that runs in CodeWarrior that bangs away at
the registers of this device and the hardware runs perfectly using the
.cfg script settings..
>
>
> 3. Have you created a bus functional model of the processor bus
> that you have then run with your FPGA bus in ModelSim to
> confirm that your FPGA performs correctly.
Yes, we have. Also, checked in h/w (see 2 above)
>
>
> 4. Have you tried burst and non-burst access by either using
> DMA, or treating the memory area as cacheable or non-cacheable?
> Have you checked those cases with simulation and then
> with a scope or logic analyzer?
Always non-burst at this point.
>
> 5. Did you try running stand-alone tests in U-Boot, to go for a
> more bare-metal debug approach?
I assume the bare-metal debug approach is using a JTAG debugger
connection and CodeWarrior. We started there and now are trying to
access the same device(s) via linux drivers.
>
> No point in debugging software if you have no idea whether the
> hardware behaves. So confirm that you have tested your hardware
> first.
>
> My board design uses the MPC8349EA, I have an Altera Stratix II
> FPGA on the local bus. I use GPCM to access flash on the local
> bus via the FPGA, and UPM to access FPGA registers. I don't
> have boards yet, but I've got a pretty good handle on how the
> interface should work.
>
> Cheers,
> Dave
>
>
>
--
Sometimes I feel like a red shirt in the Star Trek episode of life.
--
This message contains confidential information and is intended only for the
individual named. If you are not the intended recipient you should not
disseminate, distribute or copy this e-mail. Please notify the sender
immediately by e-mail if you have received this e-mail by mistake and delete
this e-mail from your system.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: mmap + segfaults on MPC8349E
2007-12-11 1:53 ` R. Ebersole (VTI - new)
@ 2007-12-11 2:16 ` David Hawkins
2007-12-15 6:40 ` R. Ebersole (VTI - new)
0 siblings, 1 reply; 6+ messages in thread
From: David Hawkins @ 2007-12-11 2:16 UTC (permalink / raw)
To: R. Ebersole (VTI - new); +Cc: linuxppc-embedded
Hi,
>> You haven't really provided enough information.
>
> Sorry about that. I grabbed one of the h/w guys to help out.
No problem. Just wanted to check the basics had been covered.
Sounds like they have.
> On the local bus frequency is 33.0 MHz. (66.0 PCI_CLK_IN). See the
> attached .cfg script for memory map.
It got dropped by the mailer. Don't sweat it.
>> 2. If its on the local bus, do you access it using GPCM or UPM?
>> Have you setup either correctly?
>> Have you confirmed the bus timing with a logic analyzer?
>
> GPCM.
> We have confirmed the timing both in functionality (in the debugger) and
> with a logic analyzer (plus oscope for setup and hold times).
> We have stand-alone C-code that runs in CodeWarrior that bangs away at
> the registers of this device and the hardware runs perfectly using the
> .cfg script settings..
Great.
>> 3. Have you created a bus functional model of the processor bus
>> that you have then run with your FPGA bus in ModelSim to
>> confirm that your FPGA performs correctly.
>
> Yes, we have. Also, checked in h/w (see 2 above)
Nice :)
>> 4. Have you tried burst and non-burst access by either using
>> DMA, or treating the memory area as cacheable or non-cacheable?
>> Have you checked those cases with simulation and then
>> with a scope or logic analyzer?
>
> Always non-burst at this point.
Are you sure?
When I was playing with the Yosemite board, I was having trouble
with a PCI card due to caching ... here's a code snippet from
the mmap routine of a driver:
/* Flags to stop the processor treating PCI memory as
* cacheable (see asm-ppc/pgtable.h)
*
* (thanks to Travis Sawyer from the ppc-embedded list)
*
* I could have used '#ifdef CONFIG_44x', but 40x uses
* these flags too, as do other processors. So just check
* whether the flag exists.
*
* TODO:
* p425 Rubini; use pgprot_noncached()
*
* asm-ppc/pgtable.h defines it as setting these two flags
*
* So, that appears to be the 'portable' way to do it.
*
* drivers/char/mem.c uses pgprot_noncached()
*/
#ifdef pgprot_noncached
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
#endif
In that particular case, I think I wasn't seeing data transferred
to the bus until a cache flush occurred. Its possible that in your
case a burst is triggered to your hardware.
How does your BFM+simulation react to bus bursts?
Can you probe the bus when you trigger the seg-fault to see
if caching is the problem?
I'm not sure that a bus error can cause a segfault. When I
get my boards, I'll generate bus parity errors to see what
kernel routines it triggers. So, chances are this is not
the source of your error.
>> 5. Did you try running stand-alone tests in U-Boot, to go for a
>> more bare-metal debug approach?
>
> I assume the bare-metal debug approach is using a JTAG debugger
> connection and CodeWarrior. We started there and now are trying to
> access the same device(s) via linux drivers.
Yep, sounds good.
Ok, so assuming you come back with the fact that the seg-fault
occurs without bursting. Lets take a look at your driver code.
Cheers,
Dave
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: mmap + segfaults on MPC8349E
2007-12-11 2:16 ` David Hawkins
@ 2007-12-15 6:40 ` R. Ebersole (VTI - new)
2007-12-15 19:55 ` David Hawkins
0 siblings, 1 reply; 6+ messages in thread
From: R. Ebersole (VTI - new) @ 2007-12-15 6:40 UTC (permalink / raw)
To: David Hawkins; +Cc: linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 1107 bytes --]
Dave,
Attached is the driver code that was in use when we had the problem.
(FPGA_orig.7z)
We think that we *may* have resolved the issue.
We have not, yet, completed testing the resolution, however.
Attached is the updated version of the driver (FPGArw.7z).
So far, this version appears OK when using mmap() without
MAP_FIXED. We open() the device O_RDWR | O_SYNC.
We were going to switch to using pread(), pwrite(), and ioctl() to
access the FPGA's registers, but we are going to hold off on that
for now.
David Hawkins wrote:
> Hi,
>
> Ok, so assuming you come back with the fact that the seg-fault
> occurs without bursting. Lets take a look at your driver code.
>
> Cheers,
> Dave
>
>
>
--
Sometimes I feel like a red shirt in the Star Trek episode of life.
--
This message contains confidential information and is intended only for the
individual named. If you are not the intended recipient you should not
disseminate, distribute or copy this e-mail. Please notify the sender
immediately by e-mail if you have received this e-mail by mistake and delete
this e-mail from your system.
[-- Attachment #2: FPGArw.7z --]
[-- Type: application/octet-stream, Size: 3775 bytes --]
[-- Attachment #3: FPGA_orig.7z --]
[-- Type: application/octet-stream, Size: 2544 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: mmap + segfaults on MPC8349E
2007-12-15 6:40 ` R. Ebersole (VTI - new)
@ 2007-12-15 19:55 ` David Hawkins
0 siblings, 0 replies; 6+ messages in thread
From: David Hawkins @ 2007-12-15 19:55 UTC (permalink / raw)
To: R. Ebersole (VTI - new); +Cc: linuxppc-embedded
Hi,
> Attached is the driver code that was in use when we had the problem.
> (FPGA_orig.7z)
>
> We think that we *may* have resolved the issue.
> We have not, yet, completed testing the resolution, however.
>
> Attached is the updated version of the driver (FPGArw.7z).
> So far, this version appears OK when using mmap() without
> MAP_FIXED. We open() the device O_RDWR | O_SYNC.
>
> We were going to switch to using pread(), pwrite(), and ioctl() to
> access the FPGA's registers, but we are going to hold off on that
> for now.
I had a look at a few of the user-space examples I have written
for accessing via mmap() for my own drivers, and the standard
/dev/mem driver. I've include a generic /dev/mem interface program
that I've used on a TS-7300 board (ARM-based board from Technologic
Systems). Its inline below. It should work fine on a PowerPC too.
My example code has always used open with O_RDWR and in some
cases (O_RDWR | O_SYNC) (as in the code below). The call to
mmap() uses prot set to (PROT_READ|PROT_WRITE) to match the open
mode, and for the flags MAP_SHARED, never MAP_FIXED.
From the man page for mmap()
http://linux.die.net/man/2/mmap
MAP_FIXED
Do not select a different address than the one specified.
If the memory region specified by start and len overlaps pages
of any existing mapping(s), then the overlapped part of the
existing mapping(s) will be discarded. If the specified address
cannot be used, mmap() will fail. If MAP_FIXED is specified,
start must be a multiple of the page size. Use of this option
is discouraged.
So I'm not sure why you would choose this option.
I can't say what problems selecting this option would create, as I've
never tried. It would take some walking through the kernel code to
see where this flag is used.
Did you really see a difference between the driver code versions, or
was it changing MAP_FIXED to MAP_SHARED that did the trick?
If you test with the /dev/mem driver below and have no problems,
then I would recommend using the /dev/mem mmap() routine in your
custom driver.
To track down which code change causes the SEGFAULT would require
finding out the source of the SEGFAULT. So if you can code up
something that consistently causes the error, then you should be
able to debug the kernel to see what is causing it. I haven't had
to debug this sort of thing, so can't offer much advice. If its
hard to trigger the error, then do something deliberate; generate
a parity error (eg. by reading a specific FPGA register), generate
a bus timeout, etc. If that has the same effect on your code, then
perhaps the driver can be instrumented to give you a little more
debug information.
Cheers,
Dave
/*
* mem_debug.c
*
* 5/10/07 D. W. Hawkins (dwh@ovro.caltech.edu)
*
* A debug console for read/write access to /dev/mem mapped
* areas.
*/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <unistd.h>
void display_help();
void change_mem(char *cmd);
void display_mem(char *cmd);
void process_command(char *cmd);
/* Mapped address and size */
static char *mem_addr = NULL;
static unsigned int mem_phys = 0;
static unsigned int mem_pages = 0;
static unsigned int mem_size = 0;
static void show_usage()
{
printf("\nUsage: mem_debug -a <address> -n <pages>\n"\
" -h Help (this message)\n"\
" -a <address> Hex address to start the map\n"\
" -n <pages> Number of pages to map\n\n");
}
int main(int argc, char *argv[])
{
int opt; /* getopt processing */
int fd; /* /dev/mem file descriptor */
char buf[200]; /* command processing buffer */
int len = 200;
int page_size = getpagesize();
int status;
while ((opt = getopt(argc, argv, "a:hn:")) != -1) {
switch (opt) {
case 'a':
status = sscanf(optarg, "%X", &mem_phys);
if (status != 1) {
printf("Parse error for -a option\n");
show_usage();
return -1;
}
break;
case 'h':
show_usage();
return -1;
case 'n':
mem_pages = atoi(optarg);
break;
default:
show_usage();
return -1;
}
}
if (mem_phys != (mem_phys/page_size)*page_size) {
printf("Error: the address must be page-aligned (0x%X)\n",
page_size);
return -1;
}
if (mem_pages == 0) {
mem_pages = 1;
}
mem_size = mem_pages*page_size;
/* Startup */
printf("\n------------------------\n");
printf("/dev/mem debug interface\n");
printf("========================\n\n");
/* Open /dev/mem and map it */
printf(" * open /dev/mem\n");
fd = open("/dev/mem", O_RDWR | O_SYNC);
if (fd < 0) {
printf("Open /dev/mem failed - %s\n",
strerror(errno));
return -1;
}
printf(" * map %d page(s) (%d-bytes) at address 0x%.8X\n",
mem_pages, mem_size, mem_phys);
mem_addr = (char *)mmap(
0,
mem_size,
PROT_READ|PROT_WRITE,
MAP_SHARED,
fd,
mem_phys);
if (mem_addr == (char *)MAP_FAILED) {
printf("Error: mmap failed\n");
close(fd);
return -1;
}
/* Display help */
display_help();
/* Process commands */
while (1) {
printf("CMD> ");
fflush(stdout);
fgets(buf,len,stdin);
process_command(buf);
}
/* Cleanup */
munmap((void *)mem_addr, mem_pages*page_size);
close(fd);
return 0;
}
/*--------------------------------------------------------------------
* User interface
*--------------------------------------------------------------------
*/
void display_help()
{
printf("\n ? Help\n");
printf(" dw addr len Display len words starting from addr\n");
printf(" db addr len Display len bytes starting from addr\n");
printf(" cw addr val Change word at addr to val\n");
printf(" cb addr val Change byte at addr to val\n");
printf(" q Quit\n");
printf("\n Notes:\n");
printf(" * addr, len, and val are interpreted as hex values\n");
printf(" * addresses are always byte based\n");
printf(" * addresses are offsets relative to the base address\n\n");
}
void process_command(char *cmd)
{
if (cmd[0] == '\0') {
return;
}
switch (cmd[0]) {
case '?':
display_help();
break;
case 'd':
case 'D':
display_mem(cmd);
break;
case 'c':
case 'C':
change_mem(cmd);
break;
case 'q':
case 'Q':
exit(0);
default:
break;
}
return;
}
void display_mem(char *cmd)
{
char width = 0;
int addr = 0;
int len = 0;
int status;
int i, data;
/* d, db, dw */
status = sscanf(cmd, "%*c%c %x %x", &width, &addr, &len);
if (status != 3) {
printf("syntax error (use ? for help)\n");
return;
}
if (len > mem_size) {
len = mem_size;
}
/* Convert to offset if required */
if (addr >= mem_phys) {
addr -= mem_phys;
}
if (addr >= mem_size) {
printf("Illegal address\n");
return;
}
switch (width) {
case 'b':
for (i = 0; i < len; i++) {
if ((i%16) == 0) {
printf("\n%.8X: ", mem_phys + addr + i);
}
data = (int)(mem_addr[addr+i]) & 0xFF;
printf("%.02X ", data);
}
printf("\n");
break;
default:
for (i = 0; i < len; i+=4) {
if ((i%16) == 0) {
printf("\n%.8X: ", mem_phys + addr + i);
}
data = *(int *)(mem_addr + addr + i);
printf("%.08X ", data);
}
printf("\n");
break;
}
printf("\n");
return;
}
void change_mem(char *cmd)
{
char width = 0;
int addr = 0;
int data = 0;
int status;
/* c, cb, cw */
status = sscanf(cmd, "%*c%c %x %x", &width, &addr, &data);
if (status != 3) {
printf("syntax error (use ? for help)\n");
return;
}
/* Convert to offset if required */
if (addr >= mem_phys) {
addr -= mem_phys;
}
if (addr >= mem_size) {
printf("Illegal address\n");
return;
}
switch (width) {
case 'b':
mem_addr[addr] = data & 0xFF;
break;
default:
*(int *)(mem_addr + addr) = data;
break;
}
return;
}
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2007-12-15 19:56 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-12-09 2:44 mmap + segfaults on MPC8349E R. Ebersole (VTI - new)
2007-12-09 4:01 ` David Hawkins
2007-12-11 1:53 ` R. Ebersole (VTI - new)
2007-12-11 2:16 ` David Hawkins
2007-12-15 6:40 ` R. Ebersole (VTI - new)
2007-12-15 19:55 ` David Hawkins
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).