Re: [LTP] [Automated-testing] Call for nommu LTP maintainer [was: Re: [PATCH 00/36] Remove UCLINUX from LTP]

Greg Ungerer
2024-01-11T13:19:45Z

On 11/1/24 23:11, Geert Uytterhoeven wrote:
> Hi Rob,
>
> On Wed, Jan 10, 2024 at 8:17 PM Rob Landley <rob@landley.net> wrote:
>> You can't fork() on nommu because copies of the mappings have different
>> addresses, meaning any pointers in the copied mappings would point into the OLD
>> mappings (belonging to the parent process), and fixing them up is 100%
>> equivalent to the "garbage collection in C" problem. (It's AI-complete. Of the
>> C3PO kind, not the "autocorrect with syntax checking" kind.) People get hung up
>> on the "it would be very inefficient to do that because no copy-on-write"
>> problem and miss the "the child couldn't FUNCTION because its pointer variables
>> all contain parent addresses" problem.
>
> Actually you can implement fork(), if you teach the compiler to use
> separate stacks for return addresses and data:
> - The first stack would contain only absolute addresses, to be
> relocated after copying,
> - The second stack would contain integers and relative pointers
> (see FDPIC below), which do not need relocation after copying.
>
>> The OTHER fun thing about nommu is you can't run conventional ELF binaries,
>> because everything is linked at fixed address. So you might be able to run ONE
>> instance of the program as your init task, assuming those addresses were
>> available even then, but as soon as you try to run a second one it's a conflict.
>>
>> The quick and dirty work around is to make PIE binaries, which can relocate
>> everything into available space, which works but doesn't scale. The problem with
>> ELF PIE is that everything is linked contiguously from a single base pointer,
>> meaning your text, rodata, data, and bss segments are all one linear blob. So if
>> you run two instances of bash, you've loaded two copies of the test and the
>> rodoata. This fills up your memory fast.
>>
>> AND PIE requires contiguous memory, which nommu is bad at providing because it
>> has no page tables to remap stuff. With an mmu it can coalesce scattered
>> physical pages into a virtually contiguous range, but without an mmu you can
>> have plenty of memory free but in tiny chunks, none big enough to satisfy an
>> allocation request.
>>
>> So they invented FDPIC, which is ELF with FOUR base pointers. Each major section
>> (rodata, text, data, and bss) has its own base pointer, so you need to find
>> smaller chunks of memory to load them into (and thus it can work on a more
>> fragmented system), AND it means that two instances of the same program can
>> share the read-only sections (rodata and text) so you only need new copies of
>> the writeable segments (data and bss. And the heap. And the stack.)
>
> Or Amiga LoadSeg() relocatable binaries and shared libraries ;-)
> As this supported splitting code, data, and bss in lots of smaller
> hunks, it could counter fragmented memory quite well.
>
> BTW, can't you run and thus test nommu-binaries under normal Linux, too?

Yes, you can. The flat format loader can be built for MMU arm and m68k Linux.
It will happily load and run flat format binaries on normal VM Linux.
I test that often on m68k (on ColdFire platforms).

Regards
Greg