1f08c3bdfSopenharmony_ci-------------
2f08c3bdfSopenharmony_ci--- Intro ---
3f08c3bdfSopenharmony_ci-------------
4f08c3bdfSopenharmony_ci
5f08c3bdfSopenharmony_ciLinux running on processors without a memory management unit place certain
6f08c3bdfSopenharmony_cirestrictions on the userspace programs.  Here we will provide some guidelines
7f08c3bdfSopenharmony_cifor people who are not familiar with such systems.
8f08c3bdfSopenharmony_ci
9f08c3bdfSopenharmony_ciIf you are not familiar with virtual memory, you might want to review some
10f08c3bdfSopenharmony_cibackground such as:
11f08c3bdfSopenharmony_ci	http://en.wikipedia.org/wiki/Virtual_Memory
12f08c3bdfSopenharmony_ci	/usr/src/linux/Documentation/nommu-mmap.txt
13f08c3bdfSopenharmony_ci
14f08c3bdfSopenharmony_ci----------------------------
15f08c3bdfSopenharmony_ci--- No memory protection ---
16f08c3bdfSopenharmony_ci----------------------------
17f08c3bdfSopenharmony_ci
18f08c3bdfSopenharmony_ciBy virtue of every process getting its own virtual memory space, applications
19f08c3bdfSopenharmony_ciare protected from each other.  So a bad memory access in one will not affect
20f08c3bdfSopenharmony_cithe memory of another.  When processors forgo virtual memory, they typically
21f08c3bdfSopenharmony_cido not add memory protection back in to the hardware.  There are one or two
22f08c3bdfSopenharmony_ciexceptions to this rule, but for now, we'll assume no one supports it.
23f08c3bdfSopenharmony_ci
24f08c3bdfSopenharmony_ciIn practical terms, this means you cannot dereference bad pointers directly
25f08c3bdfSopenharmony_ciand expect the kernel to catch and kill your application.  However, you can
26f08c3bdfSopenharmony_ciexpect the kernel to catch some bad pointers when given to system calls.
27f08c3bdfSopenharmony_ci
28f08c3bdfSopenharmony_ciFor example, this will "work" in the sense that no signal will be sent:
29f08c3bdfSopenharmony_ci	char *foo = NULL;
30f08c3bdfSopenharmony_ci	foo[0] = 'a';
31f08c3bdfSopenharmony_ci	foo[1] = 'b';
32f08c3bdfSopenharmony_ci
33f08c3bdfSopenharmony_ciHowever, the kernel should return errors when using "standard" bad pointers
34f08c3bdfSopenharmony_ciwith system calls.  Such as:
35f08c3bdfSopenharmony_ci	char *foo = NULL;
36f08c3bdfSopenharmony_ci	write(1, foo, 10);
37f08c3bdfSopenharmony_ci	-> kernel will return EFAULT or similar
38f08c3bdfSopenharmony_ciThe other bad pointer you can rely on in your tests is -1:
39f08c3bdfSopenharmony_ci	char *foo = (void *)-1;
40f08c3bdfSopenharmony_ci	read(0, foo, 10);
41f08c3bdfSopenharmony_ci	-> kernel will return EFAULT or similar
42f08c3bdfSopenharmony_ci
43f08c3bdfSopenharmony_ciOtherwise, no bad pointer may reliably be tested, either directly or
44f08c3bdfSopenharmony_ciindirectly via the kernel.  This tends to be a large part of the UCLINUX
45f08c3bdfSopenharmony_ciifdef code that shows up in LTP.
46f08c3bdfSopenharmony_ci
47f08c3bdfSopenharmony_ci----------------
48f08c3bdfSopenharmony_ci--- No forks ---
49f08c3bdfSopenharmony_ci----------------
50f08c3bdfSopenharmony_ci
51f08c3bdfSopenharmony_ciThe ubiquitous fork() function relies completely on the Copy On Write (COW)
52f08c3bdfSopenharmony_cifunctionality provided by virtual memory to share pages between processes.
53f08c3bdfSopenharmony_ciSince this isn't feasible without virtual memory, there is no fork() function.
54f08c3bdfSopenharmony_ciYou will either get a linker error (undefined reference to fork) or you will
55f08c3bdfSopenharmony_ciget a runtime failure of ENOSYS.
56f08c3bdfSopenharmony_ci
57f08c3bdfSopenharmony_ciTypically, fork() is used for very few programming paradigms:
58f08c3bdfSopenharmony_ci	- daemonization
59f08c3bdfSopenharmony_ci	- run a program
60f08c3bdfSopenharmony_ci	- parallelism
61f08c3bdfSopenharmony_ci
62f08c3bdfSopenharmony_ciFor the daemonization functionality, simply use the daemon() function.  This
63f08c3bdfSopenharmony_ciworks under both MMU and NOMMU systems.
64f08c3bdfSopenharmony_ci
65f08c3bdfSopenharmony_ciTo run a program, simply use vfork() followed by an exec-style function.
66f08c3bdfSopenharmony_ciAnd change the error handler in the child from exit() to _exit().  This too
67f08c3bdfSopenharmony_ciworks under both MMU and NOMMU systems.  But be aware of vfork() semantics --
68f08c3bdfSopenharmony_cisince the parent and child share the same memory process, the child has to be
69f08c3bdfSopenharmony_cicareful in what it does.  This is why the recommended construct is simply:
70f08c3bdfSopenharmony_ci	pid_t child = vfork();
71f08c3bdfSopenharmony_ci	if (vfork == 0)
72f08c3bdfSopenharmony_ci		_exit(execl(....));
73f08c3bdfSopenharmony_ci
74f08c3bdfSopenharmony_ciFor parallelism where processes use IPC to work together, you have to options,
75f08c3bdfSopenharmony_cineither of which are easy.  You can rewrite to use threads, or you can re-exec
76f08c3bdfSopenharmony_ciyourself with special flags to pass along updated runtime state.  This is what
77f08c3bdfSopenharmony_cithe self_exec() helper function in LTP is designed for.
78f08c3bdfSopenharmony_ci
79f08c3bdfSopenharmony_ci-------------------------
80f08c3bdfSopenharmony_ci--- No overcommitting ---
81f08c3bdfSopenharmony_ci-------------------------
82f08c3bdfSopenharmony_ci
83f08c3bdfSopenharmony_ciVirtual memory allows people to do malloc(128MiB) and get back a buffer that
84f08c3bdfSopenharmony_cibig.  But that buffer is only of virtual memory, not physical.  On a NOMMU
85f08c3bdfSopenharmony_cisystem, the memory comes immediately from physical memory and takes it away
86f08c3bdfSopenharmony_cifrom anyone else.
87f08c3bdfSopenharmony_ci
88f08c3bdfSopenharmony_ciAvoid large mallocs.
89f08c3bdfSopenharmony_ci
90f08c3bdfSopenharmony_ci---------------------
91f08c3bdfSopenharmony_ci--- Fragmentation ---
92f08c3bdfSopenharmony_ci---------------------
93f08c3bdfSopenharmony_ci
94f08c3bdfSopenharmony_ciOn a MMU system, when physical memory gets fragmented, things slow down.  But
95f08c3bdfSopenharmony_cithey keep working.  This is because every new process gets a clean virtual
96f08c3bdfSopenharmony_cimemory address space.  While processes can fragment their own virtual address
97f08c3bdfSopenharmony_cispace, this usually takes quite a long time and a lot of effort, so generally
98f08c3bdfSopenharmony_ciit is not a problem people hit.
99f08c3bdfSopenharmony_ci
100f08c3bdfSopenharmony_ciOn a NOMMU system, when physical memory gets fragmented, access to large
101f08c3bdfSopenharmony_cicontiguous blocks becomes unavailable which means requests fail.  Even if your
102f08c3bdfSopenharmony_cisystem has 40MiB _total_ free, the largest contiguous block might only be 1MiB
103f08c3bdfSopenharmony_ciwhich means that allocations larger than that will always fail.
104f08c3bdfSopenharmony_ci
105f08c3bdfSopenharmony_ciBreak up your large memory allocations when possible.  Generally speaking,
106f08c3bdfSopenharmony_cisingle allocations under 2MiB aren't a problem.
107f08c3bdfSopenharmony_ci
108f08c3bdfSopenharmony_ci-----------------
109f08c3bdfSopenharmony_ci--- No paging ---
110f08c3bdfSopenharmony_ci-----------------
111f08c3bdfSopenharmony_ci
112f08c3bdfSopenharmony_ciNo virtual memory means you can't mmap() a file and only have the pages read in
113f08c3bdfSopenharmony_ci(paged) on the fly.  So if you use mmap() on a file, the kernel must allocate
114f08c3bdfSopenharmony_cimemory for it and read in all the contents immediately.
115f08c3bdfSopenharmony_ci
116f08c3bdfSopenharmony_ci---------------------
117f08c3bdfSopenharmony_ci--- No swap space ---
118f08c3bdfSopenharmony_ci---------------------
119f08c3bdfSopenharmony_ci
120f08c3bdfSopenharmony_ciSee the "No paging" section above.  For the same reason, there is no support
121f08c3bdfSopenharmony_cifor swap partitions.  Plus, nommu typically means embedded which means flash
122f08c3bdfSopenharmony_cibased storage which means limited storage space and limited number of times
123f08c3bdfSopenharmony_ciyou can write it.
124f08c3bdfSopenharmony_ci
125f08c3bdfSopenharmony_ci-------------------------
126f08c3bdfSopenharmony_ci--- No dynamic stacks ---
127f08c3bdfSopenharmony_ci-------------------------
128f08c3bdfSopenharmony_ci
129f08c3bdfSopenharmony_ciNo virtual memory means that applications can't all have their stacks at the
130f08c3bdfSopenharmony_citop of memory and allowed to grown "indefinitely" downwards.  Stack space is
131f08c3bdfSopenharmony_cifixed at process creation time (when it is first executed) and cannot grow.
132f08c3bdfSopenharmony_ciWhile the fixed size may be increased, it's best to avoid stack pressure in
133f08c3bdfSopenharmony_cithe first place.
134f08c3bdfSopenharmony_ci
135f08c3bdfSopenharmony_ciAvoid the alloca() function and use malloc()/free() instead.
136f08c3bdfSopenharmony_ci
137f08c3bdfSopenharmony_ciAvoid declaring large buffers on the stack.  Some people like to do things
138f08c3bdfSopenharmony_cisuch as:
139f08c3bdfSopenharmony_ci	char buf[PATH_MAX];
140f08c3bdfSopenharmony_ciThis will most likely smash the stack on nommu systems !  Use global variables
141f08c3bdfSopenharmony_ci(the bss), or use malloc()/free() type functions.
142f08c3bdfSopenharmony_ci
143f08c3bdfSopenharmony_ci-------------------------------
144f08c3bdfSopenharmony_ci--- No dynamic data segment ---
145f08c3bdfSopenharmony_ci-------------------------------
146f08c3bdfSopenharmony_ci
147f08c3bdfSopenharmony_ciNo virtual memory means that mappings cannot arbitrarily be extended.  Another
148f08c3bdfSopenharmony_ciprocess might have its own mapping right after yours!  This is where the brk()
149f08c3bdfSopenharmony_ciand sbrk() functions come into play.  These are most often used to dynamically
150f08c3bdfSopenharmony_ciincrease the heap space via the C library, but a few people use these manually.
151f08c3bdfSopenharmony_ci
152f08c3bdfSopenharmony_ciBest if you simply avoid them, and if you're writing tests to exercise these
153f08c3bdfSopenharmony_cifunctions specifically, make them nops/XFAIL for nommu systems.
154f08c3bdfSopenharmony_ci
155f08c3bdfSopenharmony_ci-------------------------------
156f08c3bdfSopenharmony_ci--- Limited shared mappings ---
157f08c3bdfSopenharmony_ci-------------------------------
158f08c3bdfSopenharmony_ci
159f08c3bdfSopenharmony_ciNo virtual memory means files cannot be mmapped in and have writes to it
160f08c3bdfSopenharmony_ciwritten back out to disk on the fly.  So you cannot use MAP_SHARED when
161f08c3bdfSopenharmony_cimmapping a file.
162f08c3bdfSopenharmony_ci
163f08c3bdfSopenharmony_ci-------------------------
164f08c3bdfSopenharmony_ci--- No fixed mappings ---
165f08c3bdfSopenharmony_ci-------------------------
166f08c3bdfSopenharmony_ci
167f08c3bdfSopenharmony_ciThe MAP_FIXED option to mmap() is not supported.  It doesn't even really work
168f08c3bdfSopenharmony_ciall that well under MMU systems.
169f08c3bdfSopenharmony_ci
170f08c3bdfSopenharmony_ciBest if you simply avoid it, and if you're writing tests to exercise this
171f08c3bdfSopenharmony_cioption specifically, make them nops/XFAIL for nommu systems.
172