Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

no_std support for my OS #3451

Closed
ethindp opened this issue Oct 14, 2021 · 9 comments
Closed

no_std support for my OS #3451

ethindp opened this issue Oct 14, 2021 · 9 comments

Comments

@ethindp
Copy link

ethindp commented Oct 14, 2021

I'm working on a hobby operating system and want to develop my drivers in something other than native code. I'd really like to go for web assembly but there are no good web assembly runtimes for no_std, and the only one I know of -- Wasmi -- appears very confusing to use and to work with. This is (possibly another) use-case for no_std support. Can this be done right now or do I have to try to figure out wasmi? (I'm not aware of any other Wasm runtimes, but if there's one I just don't know about, well...).

@bjorn3
Copy link
Contributor

bjorn3 commented Oct 14, 2021

Cranelift could get no_std support, but wasmtime can't as it depends on the OS for example for mapping memory with the right priveleges.

@tschneidereit
Copy link
Member

Our docs contain a fairly long explanation of our current stance on no_std, and suggestions for alternative approaches. I wonder if the answer to the first question in that section might be of interest to you?

@ethindp
Copy link
Author

ethindp commented Oct 14, 2021

@bjorn3 They could easily just use a trait for host operations. Then they could define operations for when libstd is included and just use that, and when your in no_std, you have to write that code yourself.

@tschneidereit I don't consider the majority of arguments against no_std on that page valid arguments. The only one that is a legitimate concern and that would be hard to do is CI integration. But, the rest, one by one, can be countered thusly:

  1. For platforms that don't have std, use a trait for host operations and require the program to implement functionality for mmap themselves, as I explained above. Same for anything else that wasmtime depends on.
  2. This one is just an explanation to why including libstd increases binary sizes.
  3. This "cost" isn't much, and I'll explain why below. The CI no_std build environment is a bit of a problem, as I acknowledged above, but it can be resolved.
  4. The idioms in no_std can be made a lot similar using a crate like no-std-compat. For the majority of things you use std for, just keep on using them. The only things you'll miss are things like stdio, filesystem access, threading, etc., but that isn't necessary to run web assembly and so you could easily just exclude that. Using a crate like no-std-compat lowers the supposed "cost" to new developers (which doesn't really exist, given that a lot of things you import from std come from core and alloc anyway, and it'd just be a change from std to either core or alloc depending on whether what your importing uses memory allocation or not).
  5. You now do have a use-case for no_std -- this issue (and probably many others that I haven't dug around for). But I doubt I am the first to ask for this to be implemented.
  6. no_std will always be necessary. Unless libstd suddenly stops reexporting things from core and alloc and the three get fully merged into one and I get the ability to tell libstd what my kernel supports (which does not include networking, threading, FS APIs, processes, consoles, etc.), you will always need to be able to turn this off when either (1) building for a target that does not implement all the required functionality for libstd to work; (2) writing code for a new operating system or environment that is not yet supported by libstd; or (3) developing for an environment that supports everything libstd supports but does not have a C library of some kind available yet. There are other places where libstd is not a viable option (e.g. embedded systems with very small amounts of memory) but where executing something like Wasm may be nice for security purposes.

I know that getting no_std support in might be challenging, and figuring out CI will be difficult since you'd need to have some boilerplate to bring up the system into a state where it is ready and capable of executing Wasm (that is: MMU is active, paging is enabled and configured, etc.). But it is a doable, and the boilerplate I'm talking about is the kind of boilerplate where you can pretty much write it once, perfect it and then forget about it and only touch it when you absolutely have to. It doesn't even have to be fast or the best boilerplate ever written; all it has to do is prepare the system for wasmtime. Then your off to the races.

Thoughts about all of this? (This was a pretty long reply, sorry!)

@ethindp
Copy link
Author

ethindp commented Oct 14, 2021

Update: yes, the first answer is a bit useful, but as noted in the issue, it doesn't yet support JSON targets, and that's what I'm using.

@bjorn3
Copy link
Contributor

bjorn3 commented Oct 14, 2021

For platforms that don't have std, use a trait for host operations and require the program to implement functionality for mmap themselves, as I explained above. Same for anything else that wasmtime depends on.

This has a non-trivial cost. I would love fixing the no_std support of Cranelift as it doesn't depend on an OS at all and shouldn't do so no matter what. For Wasmtime it is too much tied to the OS, with everything from mmap, files, locks, stack unwinding, ... It also has a lot of dependencies that don't support no_std which you will have to convince to add no_std support too. For most of them using traits will likely not be accepted at all due to being bad for api usability on platforms that support std.

@ethindp
Copy link
Author

ethindp commented Oct 14, 2021

@bjorn3 Oh okay, I understand now. I'm just trying to find a high performance interpreter with a (reasonably) good API that supports no_std but I can't seem to find one at all. I've found some written in other languages, but porting those to Rust would get pretty messy IMO.

@cfallin
Copy link
Member

cfallin commented Oct 15, 2021

@ethindp I'll echo what others have said about the effort involved in porting Wasmtime due to its OS-specific use of memory mapping (mainly) facilities and all of the dependencies it pulls in that are also std; but I will also note that there are more than just the two extremes of "full industrial-strength VM runtime with JIT" and "simple interpreter". More specifically I think there is room for a barebones-simple Wasm-MVP-only runtime that still uses compiled code (from Cranelift). I can imagine designing things from scratch to rely only on a pre-allocated chunk of linear memory, and avoiding a lot of the complexity that Wasmtime-like VMs have in order to support demand-paging, asynchrony, and post-MVP Wasm features. I personally at least would find that really interesting, and it might be appealing for more embedded scenarios that still need high performance.

Maybe a starting point for that could be to use the data structures that one of the "super-simple" interpreters has defined -- wasmi perhaps -- and then start to generate function bodies with Cranelift that use the same data structures.

Anyway, just a thought; best of luck with your project!

@alexcrichton
Copy link
Member

I realize it's been years since this was originally opened, but in case anyone cc'd on this issue is still interested I've opened #8341 with a proposal to add no_std support for wasmtime which would address this issue as-stated.

@alexcrichton
Copy link
Member

This is done now with documentation here to be released with Wasmtime 21, so closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants