Project Home
Project Home
Documents
Documents
Wiki
Wiki
Discussion Forums
Discussions
Project Information
Project Info
Forum Topic - shm_ctl() fails with SHMCTL_PHYS|SHMCTL_GLOBAL on ARM target: (9 Items)
   
shm_ctl() fails with SHMCTL_PHYS|SHMCTL_GLOBAL on ARM target  
This was originally posted to the tools forum and it was pointed out that this is a better place for it.

We're trying to optimize performance of our pxa270 product.

Towards that end we want to map in a region of the processors internal on-chip SRAM as shared memory.

When using SHMCTL_PHYS|SHMCTL_GLOBAL flags, shm_ctl() returns errno 89 (Function not implemented).

If we leave off the SHMCTL_GLOBAL then the code works but we need to map it GLOBAL to prevent the cache flush on context

 switch slowdown that occurs with this cache design.

The docs indicate this should be possible.

Anyone know anything about this?

Re: shm_ctl() fails with SHMCTL_PHYS|SHMCTL_GLOBAL on ARM target  
Could you post your code?
What procnto version are you using?

	Sunil.

Ken Schumm wrote:
> This was originally posted to the tools forum and it was pointed out that this is a better place for it.
> 
> We're trying to optimize performance of our pxa270 product.
> 
> Towards that end we want to map in a region of the processors internal on-chip SRAM as shared memory.
> 
> When using SHMCTL_PHYS|SHMCTL_GLOBAL flags, shm_ctl() returns errno 89 (Function not implemented).
> 
> If we leave off the SHMCTL_GLOBAL then the code works but we need to map it GLOBAL to prevent the cache flush on 
context
>  switch slowdown that occurs with this cache design.
> 
> The docs indicate this should be possible.
> 
> Anyone know anything about this?
> 
> 
> 
> _______________________________________________
> OSTech
> http://community.qnx.com/sf/go/post13790
> 
Re: shm_ctl() fails with SHMCTL_PHYS|SHMCTL_GLOBAL on ARM target  
The problem can easily be replicated by using the sharephyscreator.c example in the shm_ctl() documentation by ORing the
 SHMCTL_GLOBAL to the shm_ctl() flags.

In our case we are using a 16k block at address 0x5c000000, which is the base address of physical PXA270 onboard SRAM.
Re: shm_ctl() fails with SHMCTL_PHYS|SHMCTL_GLOBAL on ARM target  
What procnto version are using (eg. uname -a output)?

	Sunil.

Ken Schumm wrote:
> The problem can easily be replicated by using the sharephyscreator.c example in the shm_ctl() documentation by ORing 
the SHMCTL_GLOBAL to the shm_ctl() flags.
> 
> In our case we are using a 16k block at address 0x5c000000, which is the base address of physical PXA270 onboard SRAM.

> 
> 
> _______________________________________________
> OSTech
> http://community.qnx.com/sf/go/post13834
> 
Re: shm_ctl() fails with SHMCTL_PHYS|SHMCTL_GLOBAL on ARM target  
The following code seems to work for me on an ARM926 based board using either
a 632 or a 640 procnto. Can you verify if this fails for you?

#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/neutrino.h>
#include <sys/stat.h>

main(int argc, char *argv[])
{
         int         fd;
         char        *name = "/foo";
         void        *vaddr;
         uint64_t    paddr = 0x5c000000;
         int         size = 16384;

         fd = shm_open(name, O_RDWR | O_CREAT, 0);
         if (fd == -1) {
                 perror("shm_open");
                 exit(1);
         }

         if (shm_ctl(fd, SHMCTL_GLOBAL|SHMCTL_PHYS, paddr, size) == -1) {
             perror("shm_ctl");
             shm_unlink(name);
             exit(1);
         }

         vaddr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
         if (vaddr == MAP_FAILED) {
                 perror("mmap");
                 shm_unlink(name);
                 exit(1);
         }
         close(fd);
         printf("mmap successful: vaddr=%x\n", vaddr);
         munmap(vaddr, size);
         shm_unlink(name);
         exit(0);
}

Ken Schumm wrote:
> The problem can easily be replicated by using the sharephyscreator.c example in the shm_ctl() documentation by ORing 
the SHMCTL_GLOBAL to the shm_ctl() flags.
> 
> In our case we are using a 16k block at address 0x5c000000, which is the base address of physical PXA270 onboard SRAM.

> 
> 
> _______________________________________________
> OSTech
> http://community.qnx.com/sf/go/post13834
> 
Re: shm_ctl() fails with SHMCTL_PHYS|SHMCTL_GLOBAL on ARM target  
Thanks, Sunil.

It sort of works but we're still having some hard to understand problems.

The original code calculated the address, and it was off by one, so it wasn't on a page boundary which caused errno 89 
(sort of confusing). The test code that we lifted from the shm_ctl() example mapped in address 0xb8000 which isn't valid
 in our memory map and also returned errno 89 (also confusing). I tested it with 0x5c000000 and thought it failed but 
maybe I left a zero off on the command line and the support guys who replicated it may have done the same.

Anyway, your code allows PHYS|GLOBAL to work, but when we map the buffer in with those flags code that used to work now 
inexplicably SIGSEGVs. Two processes share that space and they both use the same library code to map it in, each process
 can read and write to the shared region, but at some point a read causes a SIGSEGV even though the pointer is VALID and
 points to the correct physical address mphys() reports.

The same code works fine when the region is mmap()'d in directly from physical space (different virtual pointer values 
in each process) but not when mmap'd in using the fd from the shm_ctl() call, even though the physical address is the 
same in both cases.

I'll try to put together some sample code to see if it can easily be reproduced, but if you have any insight to share as
 to why this could happen I'd like to hear it.

Thanks for your help.
Re: shm_ctl() fails with SHMCTL_PHYS|SHMCTL_GLOBAL on ARM target  
I failed to mention that when the code SIGSEGVs the reported address seems correct, like this:

Process 544791 (LMDispatcher) terminated SIGSEGV code=2 fltno=11 ip=001021a0 ref=811000004

Where 81100004 is the virtual pointer, mphys() translates that to physical address 0x5c030004, and the physical base 
address of the shared region is 0x5c030000 so the address appears valid.
Re: shm_ctl() fails with SHMCTL_PHYS|SHMCTL_GLOBAL on ARM target  
Ken Schumm wrote:
> Thanks, Sunil.
> 
> It sort of works but we're still having some hard to understand problems.
> 
> The original code calculated the address, and it was off by one, so it wasn't on a page boundary which caused errno 89
 (sort of confusing).

The address and size must be page aligned.
Otherwise the shm_ctl() fails - and all failures come back with ENOSYS.
That is confusing and it should probably return different errno values
for different error conditions...

> The test code that we lifted from the shm_ctl() example mapped in address 0xb8000 which isn't valid in our memory map 
and also returned errno 89 (also confusing).

That I don't understand - any (page-aligned) value should be OK for the
physical address.

> I tested it with 0x5c000000 and thought it failed but maybe I left a zero off on the command line and the support guys
 who replicated it may have done the same.
> 
> Anyway, your code allows PHYS|GLOBAL to work, but when we map the buffer in with those flags code that used to work 
now inexplicably SIGSEGVs. Two processes share that space and they both use the same library code to map it in, each 
process can read and write to the shared region, but at some point a read causes a SIGSEGV even though the pointer is 
VALID and points to the correct physical address mphys() reports.

There is a bug in the 632 code where the book-keeping for the global
mappings wasn't always being done correctly which meant that after
various combinations of context switches the page tables don't have
the correct permissions.

There is a workaround for this:
- if all accessing processes have used ThreadCtl(_NTO_TCTL_IO) to gain I/O
   privilege, you can use SHMCTL_PRIV in the shm_ctl call.
- otherwise, use SHMCTL_LOWERPROT

Either of these will not use the per-process protection gear so the bug
will not manifest itself.

> The same code works fine when the region is mmap()'d in directly from physical space (different virtual pointer values
 in each process) but not when mmap'd in using the fd from the shm_ctl() call, even though the physical address is the 
same in both cases.

mmap(MAP_SHARED|MAP_PHYS) will create the mapping in the normal process
address space. The shm_ctl/mmap combination creates a mapping at virtual
addresses that are globally visible to all processes.

	Sunil.
Re: shm_ctl() fails with SHMCTL_PHYS|SHMCTL_GLOBAL on ARM target  
Yes! That fixes it very well.

You, sir, are a genius!

Thank you very much.