Multi-tasking without MMU: How?

Discussions on more advanced topics such as monolithic vs micro-kernels, transactional memory models, and paging vs segmentation should go here. Use this forum to expand and improve the wiki!
technix
Member
Member
Posts: 28
Joined: Sun Jun 16, 2013 10:13 am

Multi-tasking without MMU: How?

Post by technix »

Those STM32F7 chips looks cool: they supports large DRAM blocks and have a QSPI controller with XIP so I can have 128MB RAM and 64MB ROM easily. Now I want to multitask on this. Oh it doesn't have a MMU...

Now how can I multitask without a MMU?
User avatar
bzt
Member
Member
Posts: 1584
Joined: Thu Oct 13, 2016 4:55 pm
Contact:

Re: Multi-tasking without MMU: How?

Post by bzt »

technix wrote:Now how can I multitask without a MMU?
Simple, multitask and MMU are unrelated things.

Imagine that you have two processes A and B. A is loaded at address 0x8000 while B is loaded at 0xF000. When A yields (or a timer interrupt happens), then you save the current instruction pointer (along with other registers) for A. Then you load the instruction pointer (and other registers) for B. The execution continues on B.

This is similar with MMU, the only difference is, that you also save and restore the memory mappings. This means both A and B can be loaded at 0x8000, but that's all. Without MMU, they share the same address space, so their addresses must be different. This is irrelevant from multitasking's point of view, only the number of things to be saved and restored changes.

Cheers,
bzt
nullplan
Member
Member
Posts: 1767
Joined: Wed Aug 30, 2017 8:24 am

Re: Multi-tasking without MMU: How?

Post by nullplan »

Yep, pretty much what bzt said. Note that running without MMU requires you to use an ABI that provides for position independence (you can just use plain ELF with only PIEs allowed, or run ELF FDPIC), since only one program can ever be in one place in physical memory at a time. And without MMU there is also no memory protection, so you kind of have to hope that nothing steps on other programs' (or even the kernel's) address spaces.
Carpe diem!
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: Multi-tasking without MMU: How?

Post by Solar »

Related: Amiga's LibraryBase for a description of how AmigaOS handled exactly this setup.
Every good solution is obvious once you've found it.
User avatar
Schol-R-LEA
Member
Member
Posts: 1925
Joined: Fri Oct 27, 2006 9:42 am
Location: Athens, GA, USA

Re: Multi-tasking without MMU: How?

Post by Schol-R-LEA »

One thing I will recommend is considering a Microkernel design¹ for this use. Why? Because it is exactly the scenario for which micro-kernels were originally developed - the primary goal of a micro is not to keep the kernel small, but to provide a layer of separation between the drivers and the kernel proper, so the lack of memory protection isn't as severe a problem.

(I am aware that memory mapping and memory protection are separate issues, but in most systems the two functions are handled by the MMU, and are tightly coupled in their operations. This has been the case for the ARM designs I have studied in the past, IIRC.)

I realize that a micro-kernel may not suit your intended design, but I would still recommend taking a look at the model and see if anything about it is useful to you.

Now, I don't know the CPU in question, but I had the impression that all ARM designs have, at the very least, a high-low separation for the kernel. I am not certain how this is done without an MMU, other than possibly having two separate memory spaces, with a portion of the memory wired directly to the region about 2GB. I am pretty sure this isn't the case, so I can only guess I am mistaken about ARM always having a Supervisor mode separation.

Given that, I am assuming that in this instance, the microcontroller is always running in the equivalent of Supervisor mode, across the whole memory space. I'd have to read up on the specific model to say more.


Footnote
A key part of this - indeed, IMAO the defining property of a micro-kernel - is the replacement of specific system calls with a small set of message-passing system calls (usually just send_msg() and receive_msg() for synchronous messages, and/or mail_msg() and check_mail() for asynchronous) with all other 'system calls' being library wrappers around pre-set messages. In a 'pure' micro, these are the only mechanism for both communicating with the kernel and synchronizing between processes.

This message passing - which at once both narrows the OS interface while at the same time replacing ad-hoc system calls with a general mechanism - is the real means by which the kernel is protected from hanging, and how the risk of addressing errors (as opposed to malicious scribbling over system memory, which there isn't much one can do to prevent without memory protection) is mitigated.

My own opinion is that any system with more systems calls than those four isn't a 'pure' microkernel. However, very few if any modern micro-kernels fit this definition (purity not necessarily being desirable).
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.
User avatar
bloodline
Member
Member
Posts: 264
Joined: Tue Sep 15, 2020 8:07 am
Location: London, UK

Re: Multi-tasking without MMU: How?

Post by bloodline »

technix wrote:Those STM32F7 chips looks cool: they supports large DRAM blocks and have a QSPI controller with XIP so I can have 128MB RAM and 64MB ROM easily. Now I want to multitask on this. Oh it doesn't have a MMU...

Now how can I multitask without a MMU?
My own kernel project is exactly this, my previous operating system work was on small ARM microcontrollers, without MMU.

The MMU is irrelevant for multitasking; The key is having separate user and supervisor stacks, and a regular (timer) interrupt to handle the task switch. When the system enters an interrupted state, the current running task's CPU state is pushed on it's own stack, then the CPU enters supervisor mode with it's own stack, now it is simple enough to swap the current user stack for the stack of another task and then return from the interrupt. Now the state of the other task will be loaded into the CPU and it will run, until the next task switching interrupt, where the process repeats.

Very importantly you need a more advanced memory allocation function than a simple heap allocator, but nothing that a nice doubly linked list can't provide.
CuriOS: A single address space GUI based operating system built upon a fairly pure Microkernel/Nanokernel. Download latest bootable x86 Disk Image: https://github.com/h5n1xp/CuriOS/blob/main/disk.img.zip
Discord:https://discord.gg/zn2vV2Su
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: Multi-tasking without MMU: How?

Post by Solar »

Schol-R-LEA wrote:One thing I will recommend is considering a Microkernel design¹ for this use. Why? Because it is exactly the scenario for which micro-kernels were originally developed - the primary goal of a micro is not to keep the kernel small, but to provide a layer of separation between the drivers and the kernel proper, so the lack of memory protection isn't as severe a problem.
Also, the primary drawback of a microkernel -- high cost of frequent context switches -- is a non-issue if you don't have a context to switch and IPC boils down to passing a pointer around. ;-)
Every good solution is obvious once you've found it.
nexos
Member
Member
Posts: 1078
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

Re: Multi-tasking without MMU: How?

Post by nexos »

Solar wrote:Also, the primary drawback of a microkernel -- high cost of frequent context switches -- is a non-issue if you don't have a context to switch and IPC boils down to passing a pointer around.
You still need to context switch when messaging, even without an MMU. MMU or no MMU only effects messaging in how data is passed. You just pass a pointer. Then you would context switch to the thread you passed a message. Note that the most expensive part of a context switch, switching address spaces, no longer happens without an MMU. On x86_64, you make address space switches a lot faster with PCID, as the TLB won't be invalidated.
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: Multi-tasking without MMU: How?

Post by Solar »

That is what I meant. Whatever task switching you do, it's just the modification of a couple of values / registers. Something that's done in a few cycles. Nothing remotely as involved as switching address space and the TLB going cold.
Every good solution is obvious once you've found it.
User avatar
bloodline
Member
Member
Posts: 264
Joined: Tue Sep 15, 2020 8:07 am
Location: London, UK

Re: Multi-tasking without MMU: How?

Post by bloodline »

Solar wrote:
Schol-R-LEA wrote:One thing I will recommend is considering a Microkernel design¹ for this use. Why? Because it is exactly the scenario for which micro-kernels were originally developed - the primary goal of a micro is not to keep the kernel small, but to provide a layer of separation between the drivers and the kernel proper, so the lack of memory protection isn't as severe a problem.
Also, the primary drawback of a microkernel -- high cost of frequent context switches -- is a non-issue if you don't have a context to switch and IPC boils down to passing a pointer around. ;-)
I’m glad we have AmigaOS to demonstrate how effective (And dangerous) this can be :D
I was always fascinated by Microsoft’s Managed code operating system experiments following this model.
nexos wrote:
Solar wrote:Also, the primary drawback of a microkernel -- high cost of frequent context switches -- is a non-issue if you don't have a context to switch and IPC boils down to passing a pointer around.
You still need to context switch when messaging, even without an MMU. MMU or no MMU only effects messaging in how data is passed. You just pass a pointer. Then you would context switch to the thread you passed a message. Note that the most expensive part of a context switch, switching address spaces, no longer happens without an MMU. On x86_64, you make address space switches a lot faster with PCID, as the TLB won't be invalidated.
Solar was referring to memory context, which doesn’t need to be swapped when task switching in single address space Operating Systems!

What is PCID?
CuriOS: A single address space GUI based operating system built upon a fairly pure Microkernel/Nanokernel. Download latest bootable x86 Disk Image: https://github.com/h5n1xp/CuriOS/blob/main/disk.img.zip
Discord:https://discord.gg/zn2vV2Su
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: Multi-tasking without MMU: How?

Post by Solar »

bloodline wrote:I’m glad we have AmigaOS to demonstrate how effective (And dangerous) this can be :D
Well, I don't know about "dangerous".

The effect on the AmigaOS software scene was that developers took extra care to properly debug their appications against spurious memory access. Using tools like Valgrind and/or eFence on your projects before release was very common. Because a misbehaved program could easily crash your system, most people took pains not to be "that program" instead on relying on system security to cover for lazy programming. The ones who didn't found their tools and utilities gathering a bad rep in very short order...

So if you didn't run just about everything you found on the 'net, but ran tools that had a good track record, your user experience (not only) with regards to stability easily matched (and, IMHO, exceeded) that of comparable Windows / Linux systems of the time, and quite some time after.

And no-one was under the illusion that your system would be "secure". Today, many users assume that the OS / system will "protect" them even against malicious programs, which is genuinely untrue. I'll quote from the KeePass security FAQ:
KeePass wrote:"If a bad guy can persuade you to run his program on your computer, it's not your computer anymore".
Every good solution is obvious once you've found it.
User avatar
bloodline
Member
Member
Posts: 264
Joined: Tue Sep 15, 2020 8:07 am
Location: London, UK

Re: Multi-tasking without MMU: How?

Post by bloodline »

Solar wrote:
bloodline wrote:I’m glad we have AmigaOS to demonstrate how effective (And dangerous) this can be :D
Well, I don't know about "dangerous".

The effect on the AmigaOS software scene was that developers took extra care to properly debug their appications against spurious memory access. Using tools like Valgrind and/or eFence on your projects before release was very common. Because a misbehaved program could easily crash your system, most people took pains not to be "that program" instead on relying on system security to cover for lazy programming. The ones who didn't found their tools and utilities gathering a bad rep in very short order...

So if you didn't run just about everything you found on the 'net, but ran tools that had a good track record, your user experience (not only) with regards to stability easily matched (and, IMHO, exceeded) that of comparable Windows / Linux systems of the time, and quite some time after.

And no-one was under the illusion that your system would be "secure". Today, many users assume that the OS / system will "protect" them even against malicious programs, which is genuinely untrue. I'll quote from the KeePass security FAQ:
KeePass wrote:"If a bad guy can persuade you to run his program on your computer, it's not your computer anymore".
You can probably tell from my Avatar, that I’m not going to say anything bad about AmigaOS, I was just being realistic. By dangerous, I was really referring to the potential for data loss.

But I fundamentally agree that an Operating System which is physically secured by the user doesn’t need the OS to “nanny” the user. This is partly why I am adopting a “no memory protection" model with my current OS project. Actually I’m planning a hybrid approach, I’ll post more when I have a better working example.
CuriOS: A single address space GUI based operating system built upon a fairly pure Microkernel/Nanokernel. Download latest bootable x86 Disk Image: https://github.com/h5n1xp/CuriOS/blob/main/disk.img.zip
Discord:https://discord.gg/zn2vV2Su
User avatar
bzt
Member
Member
Posts: 1584
Joined: Thu Oct 13, 2016 4:55 pm
Contact:

Re: Multi-tasking without MMU: How?

Post by bzt »

Hi,

I've found this asm on one of my archives. It was a participant on a 512-byte contest for fasm. It is a very minimal OS with two tasks and implements multitasking without MMU.
Maybe it's going to be useful to you to understand the concept.
bloodline wrote:This is partly why I am adopting a “no memory protection" model with my current OS project.
Maybe newcomers not aware, but Microsoft had a research operating system just like that. It did not use any hardware protection, instead relied on "software isolated processes" and strong type checks in the compiler.

Cheers,
bzt
Attachments
nanoos2.zip
Nano OS, multitasking system in a boot sector
(4.44 KiB) Downloaded 82 times
nexos
Member
Member
Posts: 1078
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

Re: Multi-tasking without MMU: How?

Post by nexos »

bloodline wrote:What is PCID?
PCID basically allows multiple PML4s (the equivalent of a page directory in x86_64) to be in the TLB. They are tagged with a tag called a page context identifier that is put it the lower 12 bits of the CR3 register. This means that the TLB isn't invalidated. I believe use of it mitigates Spectre. You can read about it the Intel SDM.
Last edited by nexos on Fri Oct 16, 2020 7:19 am, edited 1 time in total.
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg
User avatar
bloodline
Member
Member
Posts: 264
Joined: Tue Sep 15, 2020 8:07 am
Location: London, UK

Re: Multi-tasking without MMU: How?

Post by bloodline »

nexos wrote:
bloodline wrote:What is PCID?
PCID basically allows multiple PML4s (the equivalent of a page directory in x86_64) to be in the PML4. They are tagged with a tag called a page context identifier that is put it the lower 12 bits of the CR3 registers. This means that the TLB isn't invalidated. I believe use of it mitigates Spectre. You can read about it the Intel SDM.
This sounds interesting! I’m going to have some fun bed time reading, many thanks for telling me about it! :)
CuriOS: A single address space GUI based operating system built upon a fairly pure Microkernel/Nanokernel. Download latest bootable x86 Disk Image: https://github.com/h5n1xp/CuriOS/blob/main/disk.img.zip
Discord:https://discord.gg/zn2vV2Su
Post Reply