|
| 1 | +[DomminusCarnufex rs-kernel](https://dominuscarnufex.github.io/cours/rs-kernel/en.html) |
| 2 | +=== |
| 3 | + |
| 4 | +This one adds a syscall to the Linux kernel and rebuilds it. The important steps: |
| 5 | + |
| 6 | +* add a Makefile rule to build an rlib (an ar archive) using `rustc`, |
| 7 | + specifying `#![crate_type="rlib"]` in the source |
| 8 | +* extract the `.o` file from the rlib, and rename it to match the expected name |
| 9 | +* add the `.o` file to `obj-y` |
| 10 | + |
| 11 | +They also edit the syscall interrupt handler (in asm) to dispatch to |
| 12 | +their syscalls. |
| 13 | + |
| 14 | +No reference to lang items. It uses stable `#[no_std]` without `#[no_core]` - |
| 15 | +I'd expect the resulting object file just happens not to reference libcore, but |
| 16 | +more complicated objects could. |
| 17 | + |
| 18 | +No custom compiler flags etc. other than `#[no_std]`. |
| 19 | + |
| 20 | +[saschagrunert/kmod](https://github.com/saschagrunert/kmod) |
| 21 | +=== |
| 22 | + |
| 23 | +A custom Makefile drives the build, by copying a Makefile.in that looks |
| 24 | +like a normal Linux module Makefile to a build directory, and then |
| 25 | +invoking the usual `make -C /lib/modules/$(uname -r)/build M=$PWD` (see |
| 26 | +[Documentation/kbuild/modules.txt](https://www.kernel.org/doc/Documentation/kbuild/modules.txt) |
| 27 | +). |
| 28 | + |
| 29 | +The custom Makefile sets `RUSTCFLAGS` to |
| 30 | +`-O -C code-model=kernel -C relocation-model=static`. |
| 31 | + |
| 32 | +There's also a `module.c` file containing the usual `MODULE_LICENSE` |
| 33 | +etc. macros, plus prototypes for `init_module` and `cleanup_module`. |
| 34 | + |
| 35 | +Makefile.in does the following: |
| 36 | + |
| 37 | +* build the module with `cargo rustc`, specifiyng |
| 38 | + `crate_type = ['staticlib']` in Cargo.toml |
| 39 | +* set `foo-objs := module.o libfoo.a` (note that order is significant: |
| 40 | + as with shared libraries, static libraries need to come after things |
| 41 | + that depend on them) |
| 42 | +* set `obj-m := foo.o` |
| 43 | + |
| 44 | +(The `foo-objs` syntax is for "composite objects," which is documented in |
| 45 | +[Documentation/kbuild/makefiles.txt](https://kernel.org/doc/Documentation/kbuild/makefiles.txt) |
| 46 | +section 3.3, except for the bit where `-objs` is synonymous to `-y`; see |
| 47 | +[scripts/Makefile.lib](https://github.com/torvalds/linux/blob/master/scripts/Makefile.lib) |
| 48 | +for that. It works by combining the listed objects with `ld -r` aka |
| 49 | +`--relocatable` to generate `foo.o`.) |
| 50 | + |
| 51 | +I couldn't get the out-of-tree build to work right with my 3.16 (Debian |
| 52 | +oldstable) kernel; it builds fine if you get rid of the extra Makefile |
| 53 | +(rename Makefile.in to Makefile) and get rid of the `src` variable there, |
| 54 | +making it build in-tree. |
| 55 | + |
| 56 | +kmod includes two other source files besides `lib.rs` and `module.c`, |
| 57 | +which aren't very interesting. `lang_items.rs` has ~empty |
| 58 | +implementations of all three lang-items, and `print.rs` has a |
| 59 | +straightforward FFI binding to `printk`, plus a macro called `println!` |
| 60 | +that doesn't actually implement the format-string logic. These should be |
| 61 | +wired up to Linux's unwinding / OOPSing mechanisms and to `core::fmt` |
| 62 | +respectively. |
| 63 | + |
| 64 | +I can replicate the Makefile parts of this by themselves. The following |
| 65 | +Makefile successfully links a kernel module out of one.rs and two.c: |
| 66 | + |
| 67 | +```make |
| 68 | +obj-m := three.o |
| 69 | +three-objs := two.o libone.a |
| 70 | +lib%.a: %.rs |
| 71 | + rustc -o $@ -O $< |
| 72 | +``` |
| 73 | + |
| 74 | +(Since the point of this Makefile is just to make linking work, I'm |
| 75 | +being lazy and _not_ specifying `#![no_std]` in the Rust source; libstd |
| 76 | +gets copied into `libone.a` but the linker eliminates it as dead code |
| 77 | +when building `three.c`. That lets me avoid thinking about lang-items.) |
| 78 | + |
| 79 | +[tsgates/rust.ko](https://github.com/tsgates/rust.ko) |
| 80 | +=== |
| 81 | + |
| 82 | +This one is much older (2013, last updated 2016) but much more complete. |
| 83 | +It brings up a couple of important points: |
| 84 | + |
| 85 | +* You need a custom target file to set things like `disable_redzone` and |
| 86 | + no use of floating point. (Their custom target file also sets |
| 87 | + `code-model` to `kernel` and `relocation-model` to `static`, as with |
| 88 | + the previous one.) |
| 89 | + - Apparently you can just use "+soft-float" in target features these |
| 90 | + days, See [this comment on rust-lang/rfcs#1364](https://github.com/rust-lang/rfcs/issues/1364#issuecomment-234404686). |
| 91 | +* The kernel internal ABI has no guarantees at all, and you want to write |
| 92 | + against the kernel C API, using bindgen. |
| 93 | + - One limitation is that bindgen doesn't support C macros. |
| 94 | + |
| 95 | +[pmj/rustykext](https://github.com/pmj/rustykext) |
| 96 | +=== |
| 97 | + |
| 98 | +MacOS. Also uses `-C soft-float` and `-C no-redzone=y` (and `-C |
| 99 | +no-stack-check`, which is no longer necessary). |
0 commit comments