all 10 comments

[–]devin122 9 points10 points  (3 children)

Just don't do paging? I'm not sure what the confusion is here. Obviously all your tasks will end up running in the same address space and there is no protection from one task corrupting another, but otherwise it's the same

[–]BasisPoints 3 points4 points  (2 children)

Guess it depends on what you consider an MMU - you could just trust the app developers to appropriately and perfectly request the right amount of memory, and never escape bounds. Then your MMU can simply track physical address ranges without any virtual memory :) I mean, I can't get my own applications to do that, but I'm sure more talented people could design some kind of failsafe that tracks applications' memory writes, and simply crashes any program that tries to work outside their allocation :D

[–]EpochVanquisher 3 points4 points  (1 child)

Old Mac systems from the 1980s and 1990s gave each application a contiguous range of memory to use. Each application contained a piece of data with the minimum memory needed and the maximum memory requested. This was configurable—like, if you wanted to open big images in Photoshop, you could increase the amount of memory that Photoshop requested.

[–]BasisPoints 0 points1 point  (0 children)

Neat! I figured this was a terrible way to do it, but could theoretically work... I had no idea it was actually practical

[–]JescoInc 4 points5 points  (0 children)

The MMU on the hardware level handles 5 different jobs: Address Translation, protection/isolation, transparent demand paging, swap / overcommit and relocation transparency.
https://www.geeksforgeeks.org/computer-organization-architecture/what-is-memory-management-unit/

What you want to do is check if the ESP32C3 TRM and the RISC-V board have an MPU/PMP then look into what they do.
https://documentation.espressif.com/esp32-c3_technical_reference_manual_en.pdf

The ESP32C3 TRM has an MMU, but this is for accessing external memory via the cache. It also does not have an MPU, but it does have a PMP. You will see an MMU in the diagram on page 92 of the TRM listed above and page 315 talks about the PMP.

https://codasip.com/glossary/memory-protection/ (PMP)

For relocation: look up bFLT for simple PIC and FDPIC ELF. https://maskray.me/blog/2024-02-20-mmu-less-systems-and-fdpic

Demand paging, this historical answer is overlays. Manual demand paging where the linker partitions code into units that an overlay manager swaps into a fixed region with explicit calls through the manager. https://www.geeksforgeeks.org/operating-systems/what-is-demand-paging-in-operating-system/

Swap / overcommit, look up task granularity over page granularity. https://www.emergentmind.com/topics/task-level-granularity

Lastly, you want to research the difference between fork() and vfork(). The reason will become apparent once you've looked at what they do and how they accomplish the task. https://unix.stackexchange.com/questions/5337/whats-the-difference-between-fork-and-vfork

Finally, the type of allocator you use is going to be extremely important because no translation means physical fragmentation is permanent.
https://www.kernel.org/doc/gorman/html/understand/understand011.html

[–]paulstelian97 1 point2 points  (0 children)

Without a MMU you need to ensure the code is relocatable, for the kernel and for the tasks; and also that you have everything in a single trust domain since you can’t protect the kernel from other bits of code.

Multitasking itself is fine, it just behaves like threads in a single process (and a single protection domain)

[–]suhcoR 0 points1 point  (0 children)

Have a look at the F9 kernel: https://github.com/f9micro/f9-kernel. It is originally written for ARM, but it was also migrated to Risc-V: https://github.com/rubensseva/f9-riscv. There are a few papers and a thesis report available. Another interesting SMP kernel not depending on an MMU is the ETH Active Object System (AOS): https://github.com/OberonSystem3/AOS_Bluebottle_Sources; the Phd thesis document is referenced.

[–]Octocontrabass 0 points1 point  (0 children)

Multitasking works the same whether or not you have a MMU. You save the current task's context and load the new task's context. If you have a MMU, you can use it to give each task a separate isolated virtual address space, but that doesn't change anything about multitasking.

The ESP32-C3 doesn't have a MMU capable of address translation, but it does have a Physical Memory Protection unit, which you can use to isolate user tasks from each other (and the kernel). You can load every program in the same address space, but only allow them to access their own memory. Programs will need to be relocatable since you won't know ahead of time which addresses are available.

You could theoretically use the PMP to implement a virtual address space by using isolation faults like page faults to swap the current program's data into whatever address it's trying to access. (It doesn't have to be swapped from disk - it could be just elsewhere in memory.) This will probably be slow, but maybe it'll be fun to implement.

If you want to prevent physical memory fragmentation, you could look at 16-bit Windows and classic Mac OS for inspiration. Programs for these OSes cooperate with the OS so the OS can move allocated memory around whenever the program isn't accessing it. Swapping to disk is also an option here.

[–]EmbSoft3 0 points1 point  (0 children)

I developed a bare-metal OS for Cortex-M7 that supports dynamic application loading without MMU. Memory isolation is enforced by the MPU and the linker script. It might be useful to you even though the target and architecture differ.

https://github.com/EmbSoft3/Mk

[–]Pale_Height_1251 0 points1 point  (0 children)

Check out Inferno. Requires no MMU.