oxidecomputer / hubris

A lightweight, memory-protected, message-passing kernel for deeply embedded systems.
Mozilla Public License 2.0
2.93k stars 167 forks source link

Support for microcontrollers without an MPU? #326

Open stillinbeta opened 2 years ago

stillinbeta commented 2 years ago

I'm working on a project based on the NXP K20 series of processors (of Teensy 3.2 fame) and I am in need of an RTOS. Unfortunately this series of chips lack hardware memory protection.

My use case doesn't require the security guarantees an MPU would provide, but is Hubris able to function without one?

I don't mind getting my hands dirty but I want to make sure this isn't a fool's errand.

labbott commented 2 years ago

Currently it assumes an MPU but it's all contained in one function

https://github.com/oxidecomputer/hubris/blob/master/sys/kern/src/arch/arm_m.rs#L383 https://github.com/oxidecomputer/hubris/blob/master/sys/kern/src/arch/arm_m.rs#L470

It would be pretty easy to add a cfg option to not run the MPU code if you wanted to submit a PR or remove the function completely if you just want to hack.

cbiffle commented 2 years ago

@stillinbeta are you sure the K20 lacks memory protection hardware? Its datasheet is ambiguous but I've found some older Freescale marketing flyers that explicitly list an MPU among the K20's features. Perhaps it's only available on certain variants.

I would personally be more comfortable not having a way to compile out memory protection support, which is where we are today -- but it does prevent us from supporting certain microcontrollers, as you've noted, which is unfortunate.

That being said, using those microcontrollers with Rust is tricky, as rustc assumes that dereferencing a null pointer fails -- and without an MPU, on Cortex-M devices, it typically succeeds. (What's at address 0 in the K20 memory map, out of curiosity?)

Hubris can be made to work without an MPU, though much of its value proposition goes away, in my opinion -- in particular, it's no longer safe to restart tasks at a component level if bugs in their unsafe code could have destroyed anything in the system.

That's not a "no," but, we'd want to think through this carefully.

cbiffle commented 2 years ago

Hmm, another popular microcontroller that lacks the hardware we expect is the Microchip SAMD21, which is common on a lot of Adafruit boards these days (for example). The SAMD21 case is even more unfortunate, as Microchip chose to configure its Cortex-M0+ without either the MPU or privileged mode / dual stack pointers. That second case would be a real issue for Hubris even if we turned off the MPU code. (Those two features are some of the selling point of the M0+ over the M0, so I'm not sure why they did this.)

stillinbeta commented 2 years ago

@stillinbeta are you sure the K20 lacks memory protection hardware? Its datasheet is ambiguous but I've found some older Freescale marketing flyers that explicitly list an MPU among the K20's features. Perhaps it's only available on certain variants.

Yeah, I found a reference to an MMU in a tier up, the K20-100 (I have a K20-72 - one tier too low :disappointed: )

(What's at address 0 in the K20 memory map, out of curiosity?)

image

Looks like exception vectors? The docs aren't as explicit as I'd like.

Hubris can be made to work without an MPU, though much of its value proposition goes away, in my opinion -- in particular, it's no longer safe to restart tasks at a component level if bugs in their unsafe code could have destroyed anything in the system.

Understandable, and I appreciate the response! For context, I want to write firmware for a keyboard. I need an rtos of some description (the popular QMK uses Chibios), and I figure it might as well be yours!

cbiffle commented 2 years ago

That's interesting, I maintain firmware for a keyboard and we've talked about porting it to use Hubris, but haven't. (But I'm using the STM32L4 which has an MPU.)

I agree that the K20 manual suggests that exception vectors in Flash are mapped at address 0 by default, which means null dereferences will succed. That's too bad. It looks like the current versions of rustc generate null pointer checks when targeting thumbv7m, though, so, part of the crisis is averted. :-)

I'm going to leave this open for further discussion.

cbiffle commented 2 years ago

If you've found this bug because you're wanting to try Hubris on a small microcontroller, note that we have Cortex-M0+ support now. Many Cortex-M0+ chips on the market have MPUs -- the STM32G030 is among them, and is also one of the cheapest Cortex-M microcontrollers on the market.