[uClibc] mmaps for malloc should be private

David Howells dhowells at redhat.com
Tue Mar 23 15:08:37 UTC 2004


David McCullough wrote:

> Ok,  I have never bumped into frv-uclinux.  A quick Google didn't
> show up any sites where I could look at the source etc.  Do you have a
> pointer to it ?  All I can find are gcc/binutils references and a few
> hints of the uClinux port for it.

It's Fujitsu's own CPU architecture. We have done our own kernel port to
it. Most of this range of CPUs lack a full MMU, and so the kernel has a config
option to switch between normal MMU linux and uClinux.


> Do you have full shared libraries working under frv-uclinux ?

We've arranged things such that the uClibc-based userspace works on both MMU
linux and on uClinux as ELF with shared executable and shared library support.

To make this work, uClinux's mmap() support had to be changed to work more
like that on MMU linux. To summarise the way nommu mmap() works in our kernel:

 (*) no file, MAP_PRIVATE: mapping shared over clone() or vfork(), discarded
     by execve().

 (*) no file, MAP_SHARED: shared over clone() or vfork(), discarded by
     execve().

 (*) file, MAP_PRIVATE, !PROT_WRITE: mapping shareable with existing file
     mappings. File segment is loaded and retained in memory as long as refs
     exist.

 (*) file, MAP_PRIVATE, PROT_WRITE: mapping not shareable. New memory
     allocated and loaded from file when mmap() is called.

 (*) file, MAP_SHARED, !PROT_WRITE: mapping shareable with existing file
     mappings on uClinux. File segment is loaded and retained in memory as
     long as refs exist.

 (*) file, MAP_SHARED, PROT_WRITE: not supported; it would be hard to reflect
     changes to memory into the file.

 (*) device file, MAP_PRIVATE: mapping shareable and writeable at device
     driver's discretion. In particular, driver may nominate address at which
     device space is to be mapped (MAP_FIXED may be rejected).

 (*) PT_TRACED being set on a process disables sharing for that process to
     help prevent breakpoints set in one process instance from corrupting
     another process instance.

 (*) Changes made to the file after a mapping is made do not reflect on the
     mapping.


Now the ELF FDPIC model allows the individual PT_LOAD segments to be relocated
independently with respect to each other. Normally binaries will have two
PT_LOAD segments - one READ/EXEC perms, one READ/WRITE perms. What this mmap
change allows us to do is to share the R/O PT_LOAD segments and not share the
R/W PT_LOAD segments.

So what happens is that the binfmt driver mmap()'s the PT_LOAD segment as
MAP_PRIVATE with the appropriate combination of PROT_READ, PROT_WRITE and
PROT_EXEC, and mmap() looks after sharing as appropriate.


> If you look in linux-2.4.x/mmnommu/mmap.c you will find that all uClinux
> ports on uclinux.org do not support private mappings.

This makes the executable sharing a lot harder to do. How does the binfmt tell
mmap() that a data segment should _not_ be shared? There's no MAP_PRIVATE...


> Search for "Get the NO_MM specific checks done first" in do_mmap_pgoff.
>
> It explicitly prevents writable file mappings and writable private
> mappings.
>
> The first is obvious,  it isn't possible.  The second is arguable.

I agree with the first, and the second is exactly what you're doing as
MAP_SHARED/PROT_WRITE now, I think.


> I believe the reasoning for this check is that you cannot have a private
> mapping under uclinux as all memory is accessable.  This check forces
> people to think about the NOMMUness of their target a little.  Not sure
> I agree with it myself,  but it has been there a long time.

MAP_PRIVATE and MAP_SHARED don't really control whether or not other processes
can see into your address space or not... They control whether changes to the
backing memory get updated on disc, and what happens in the case of a fork().

We do _not_ implement fork() on uClinux.

What I've done is to make the uClinux kernel have a single list of VMAs in
common for all mm_structs (not processes), and I've co-opted the
mm_tblock_struct such that each mm_struct has a list of mm_tblock_struct to
point to the VMAs in which it has an interest.

As useful side effects, this permits access limitation with ptrace(), and
permits /proc/<pid>/maps and /proc/<pid>/exe to work as expected.

I've attaches a diff to show the changes made to the uClinux kernel to support this.


> Fair enough.  So the FRV has MMU and NOMMU variants that are instruction
> set compatible ?

More or less. One CPU has an MMU - which can of course be run in NOMMU mode -
and it has some extra instructions that are used to control the MMU that can
be safely ignored in NOMMU mode. However, all that only exists in kernel mode.

As far as userspace is concerned the two instruction sets are pretty much
identical, apart from some differences in the media instructions and
registers.


> Sounds like an interesting platform.  What sort of bogoMIPs, internal
> devices etc do you get with one of these ?

BogoMIPS is a little difficult to calculate - the development platforms have
no reference clock - and so we just calculate the delay loop count from the
clock speed set on DIP switches.

However, the CPUs can run anything up to 300MHz easily and probably faster.

David

-------------- next part --------------
A non-text attachment was scrubbed...
Name: ucl-mmap.diff
Type: application/octet-stream
Size: 15524 bytes
Desc: not available
Url : http://lists.busybox.net/pipermail/uclibc/attachments/20040323/991f1e72/attachment.obj 


More information about the uClibc mailing list