aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--README48
-rw-r--r--halt-rs/Cargo.toml23
-rw-r--r--halt-rs/rust-toolchain1
-rw-r--r--halt-rs/src/lib.rs13
-rw-r--r--kernel-rs/Cargo.toml22
-rw-r--r--kernel-rs/rust-toolchain1
-rw-r--r--kernel-rs/src/lib.rs17
-rw-r--r--libpintos-rs/.gitignore1
-rw-r--r--libpintos-rs/Cargo.toml16
-rw-r--r--libpintos-rs/build.rs4
-rw-r--r--libpintos-rs/rust-toolchain1
-rw-r--r--libpintos-rs/src/lib.rs6
-rw-r--r--src/Makefile.build15
-rw-r--r--src/Makefile.userprog28
-rw-r--r--src/examples/.gitignore2
-rw-r--r--src/examples/Makefile14
-rw-r--r--src/examples/rust.c6
-rw-r--r--src/examples/rust.h1
-rw-r--r--src/userprog/syscall.c36
20 files changed, 228 insertions, 29 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2c96eb1
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+target/
+Cargo.lock
diff --git a/README b/README
index e69de29..f8cc032 100644
--- a/README
+++ b/README
@@ -0,0 +1,48 @@
+This repo contains a modified version [0] of Pintos [1] in which you can write
+user programs, standard library, syscalls and kernel code in Rust and C at the
+same time.
+
+This README focuses on the Rust parts. [0] and [1] contain information about
+Pintos in general.
+
+[0]: https://www.ida.liu.se/~TDIU16/2020/info/courseinfo.sv.shtml
+[1]: https://web.stanford.edu/class/cs140/projects/pintos/pintos.html
+
+Kernel
+------
+
+The Rust kernel code is located in kernel-rs/. This is compiled and linked with
+the normal kernel before being packaged into `os.dsk`.
+
+Standard library
+----------------
+
+The Rust standard library is located in libpintos-rs/. This crate isn't compiled
+to a static library. Instead, user programs depend on this crate and let Cargo
+link them together. This means that the standard library doesn't need to `extern
+"C"` its functions.
+
+User programs
+-------------
+
+User programs can be located anywhere you want. halt-rs/ is included as an
+example. The only requirement is that they are compiled as static libraries with
+no_std and a `pub extern "C" entry()` that acts as the entry point.
+
+In order for the Pintos Makefile to build your program you need to add the
+binary's name to PROGS_RS and its crate path to $(BINARY)_SRC in
+`src/examples/Makefile`. haltrs is included as an example.
+
+The binaries are rather large, even with LTO enabled. halt-rs compiles to 4.3M
+in debug and 1.6M with --release and LTO. This isn't an issue (at least not yet)
+as the final binary when linked by the Pintos Makefile is 48k, compared with the
+mostly equivalent halt.c that compiles to 42k.
+
+TODO
+----
+
+* Merge the C and Rust kernel like we already do with the standard library.
+* Automatically copy libc.a when building libpintos-rs (via build.rs?).
+* println!-macro with formatting in libpintos-rs (and kernel?).
+* Implement an allocator that calls malloc in libpintos-rs.
+* Some sort of Cargo template for setting up new user programs.
diff --git a/halt-rs/Cargo.toml b/halt-rs/Cargo.toml
new file mode 100644
index 0000000..7486789
--- /dev/null
+++ b/halt-rs/Cargo.toml
@@ -0,0 +1,23 @@
+[package]
+name = "pintos-rs"
+version = "0.1.0"
+authors = ["Gustav Sörnäs <gustav@sornas.net>"]
+edition = "2018"
+
+[lib]
+name = "haltrs"
+crate-type = ["staticlib"]
+
+[profile.dev]
+panic = "abort"
+
+[profile.release]
+panic = "abort"
+
+[dependencies.libc]
+version = "0.2"
+default-features = false
+features = ["extra_traits"]
+
+[dependencies.libpintos]
+path = "../libpintos-rs"
diff --git a/halt-rs/rust-toolchain b/halt-rs/rust-toolchain
new file mode 100644
index 0000000..adfa491
--- /dev/null
+++ b/halt-rs/rust-toolchain
@@ -0,0 +1 @@
+nightly-i686-unknown-linux-gnu
diff --git a/halt-rs/src/lib.rs b/halt-rs/src/lib.rs
new file mode 100644
index 0000000..4ee0bdd
--- /dev/null
+++ b/halt-rs/src/lib.rs
@@ -0,0 +1,13 @@
+#![no_std]
+
+use libpintos::exit;
+
+#[panic_handler]
+fn panic(_info: &core::panic::PanicInfo) -> ! {
+ loop {}
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn entry() {
+ exit(0x42);
+}
diff --git a/kernel-rs/Cargo.toml b/kernel-rs/Cargo.toml
new file mode 100644
index 0000000..738559f
--- /dev/null
+++ b/kernel-rs/Cargo.toml
@@ -0,0 +1,22 @@
+[package]
+name = "kernel"
+version = "0.1.0"
+authors = ["Gustav Sörnäs <gustav@sornas.net>"]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[lib]
+name = "kernel"
+crate-type = ["staticlib"]
+
+[profile.dev]
+panic = "abort"
+
+[profile.release]
+panic = "abort"
+
+[dependencies.libc]
+version = "0.2"
+default-features = false
+features = ["extra_traits"]
diff --git a/kernel-rs/rust-toolchain b/kernel-rs/rust-toolchain
new file mode 100644
index 0000000..adfa491
--- /dev/null
+++ b/kernel-rs/rust-toolchain
@@ -0,0 +1 @@
+nightly-i686-unknown-linux-gnu
diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs
new file mode 100644
index 0000000..d63bb23
--- /dev/null
+++ b/kernel-rs/src/lib.rs
@@ -0,0 +1,17 @@
+#![no_std]
+
+#[panic_handler]
+fn panic(_info: &core::panic::PanicInfo) -> ! {
+ loop {}
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn syscall_handler() {
+ printf("c suger lmao xd %d\n".as_ptr(), 42);
+ thread_exit();
+}
+
+extern {
+ fn thread_exit();
+ fn printf(format: *const u8, ...);
+}
diff --git a/libpintos-rs/.gitignore b/libpintos-rs/.gitignore
new file mode 100644
index 0000000..437e1f1
--- /dev/null
+++ b/libpintos-rs/.gitignore
@@ -0,0 +1 @@
+libpintos.a
diff --git a/libpintos-rs/Cargo.toml b/libpintos-rs/Cargo.toml
new file mode 100644
index 0000000..e9293ad
--- /dev/null
+++ b/libpintos-rs/Cargo.toml
@@ -0,0 +1,16 @@
+[package]
+name = "libpintos"
+version = "0.1.0"
+authors = ["Gustav Sörnäs <gustav@sornas.net>"]
+edition = "2018"
+
+[profile.dev]
+panic = "abort"
+
+[profile.release]
+panic = "abort"
+
+[dependencies.libc]
+version = "0.2"
+default-features = false
+features = ["extra_traits"]
diff --git a/libpintos-rs/build.rs b/libpintos-rs/build.rs
new file mode 100644
index 0000000..8b9cdb4
--- /dev/null
+++ b/libpintos-rs/build.rs
@@ -0,0 +1,4 @@
+fn main() {
+ println!("cargo:rustc-link-search=native=.");
+ println!("cargo:rustc-link-lib=static=pintos");
+}
diff --git a/libpintos-rs/rust-toolchain b/libpintos-rs/rust-toolchain
new file mode 100644
index 0000000..adfa491
--- /dev/null
+++ b/libpintos-rs/rust-toolchain
@@ -0,0 +1 @@
+nightly-i686-unknown-linux-gnu
diff --git a/libpintos-rs/src/lib.rs b/libpintos-rs/src/lib.rs
new file mode 100644
index 0000000..2ad4657
--- /dev/null
+++ b/libpintos-rs/src/lib.rs
@@ -0,0 +1,6 @@
+#![no_std]
+
+#[link(name="pintos", kind="static")]
+extern {
+ pub fn exit(status: i32);
+}
diff --git a/src/Makefile.build b/src/Makefile.build
index b5474f5..22de06f 100644
--- a/src/Makefile.build
+++ b/src/Makefile.build
@@ -78,8 +78,18 @@ DEPENDS = $(patsubst %.o,%.d,$(OBJECTS))
threads/kernel.lds.s: CPPFLAGS += -P
threads/kernel.lds.s: threads/kernel.lds.S threads/loader.h
-kernel.o: threads/kernel.lds.s $(OBJECTS)
- $(LD) -T $< -o $@ $(OBJECTS)
+LIBDIR_RUST = $(SRCDIR)/../kernel-rs
+
+LIB_RUST = libkernel-rs.a
+
+$(LIB_RUST):
+ (cd $(LIBDIR_RUST) && cargo build)
+ cp $(LIBDIR_RUST)/target/debug/libkernel.a $@
+
+.PHONY: $(LIB_RUST)
+
+kernel.o: threads/kernel.lds.s $(OBJECTS) $(LIB_RUST)
+ $(LD) -T $< -o $@ $(OBJECTS) $(LIB_RUST)
kernel.bin: kernel.o
$(OBJCOPY) -O binary -R .note -R .comment -S $< $@.tmp
@@ -96,6 +106,7 @@ os.dsk: loader.bin kernel.bin
cat $^ > $@
clean::
+ (cd $(LIBDIR_RUST) && cargo clean)
rm -f $(OBJECTS) $(DEPENDS)
rm -f threads/loader.o threads/kernel.lds.s threads/loader.d
rm -f kernel.o kernel.lds.s
diff --git a/src/Makefile.userprog b/src/Makefile.userprog
index f7271fe..be47b48 100644
--- a/src/Makefile.userprog
+++ b/src/Makefile.userprog
@@ -8,6 +8,13 @@ $(PROGS): LDSCRIPT = $(SRCDIR)/lib/user/user.lds
# filst04@liu 2014-01: Added to ignore the build-id located at offset 0.
$(PROGS): LDFLAGS += $(LDFLAG_BUILD_ID)
+# Duplicate for rs
+$(PROGS_RS): CPPFLAGS += -I$(SRCDIR)/lib/user -I.
+$(PROGS_RS): LDFLAGS = -nostdlib -static -Wl,-T,$(LDSCRIPT)
+$(PROGS_RS): LDSCRIPT = $(SRCDIR)/lib/user/user.lds
+# filst04@liu 2014-01: Added to ignore the build-id located at offset 0.
+$(PROGS_RS): LDFLAGS += $(LDFLAG_BUILD_ID)
+
# Library code shared between kernel and user programs.
lib_SRC = lib/debug.c # Debug code.
lib_SRC += lib/random.c # Pseudo-random numbers.
@@ -23,13 +30,14 @@ lib/user_SRC += lib/user/console.c # Console code.
LIB_OBJ = $(patsubst %.c,%.o,$(patsubst %.S,%.o,$(lib_SRC) $(lib/user_SRC)))
LIB_DEP = $(patsubst %.o,%.d,$(LIB_OBJ))
-LIB = lib/user/entry.o libc.a
+LIB_ENTRY = lib/user/entry.o
+LIB = $(LIB_ENTRY) libc.a
PROGS_SRC = $(foreach prog,$(PROGS),$($(prog)_SRC))
PROGS_OBJ = $(patsubst %.c,%.o,$(patsubst %.S,%.o,$(PROGS_SRC)))
PROGS_DEP = $(patsubst %.o,%.d,$(PROGS_OBJ))
-all: $(PROGS)
+all: $(PROGS) $(PROGS_RS)
# filst04@liu 2014-01: Needed to not break the system call functions
# on modern Linux'es, works on SunOS too
@@ -41,7 +49,19 @@ $(1): $$($(1)_OBJ) $$(LIB) $$(LDSCRIPT)
$$(CC) $$(LDFLAGS) $$($(1)_OBJ) $$(LIB) -o $$@
endef
+define TEMPLATE_RS
+lib$(1).a:
+ (cd $$($(1)_SRC) && cargo build)
+ cp $$($(1)_SRC)/target/debug/lib$(1).a .
+.PHONY: lib$(1).a
+$(1): rust.o lib$(1).a $$(LIB_RUST) $$(LDSCRIPT)
+ $$(CC) $$(LDFLAGS) $$(LIB_ENTRY) rust.o lib$(1).a -o $$@
+clean::
+ (cd $$($(1)_SRC) && cargo clean)
+endef
+
$(foreach prog,$(PROGS),$(eval $(call TEMPLATE,$(prog))))
+$(foreach prog,$(PROGS_RS),$(eval $(call TEMPLATE_RS,$(prog))))
libc.a: $(LIB_OBJ)
rm -f $@
@@ -49,8 +69,8 @@ libc.a: $(LIB_OBJ)
ranlib $@
clean::
- rm -f $(PROGS) $(PROGS_OBJ) $(PROGS_DEP)
- rm -f $(LIB_DEP) $(LIB_OBJ) lib/user/entry.[do] libc.a
+ rm -f $(PROGS) $(PROGS_RS) $(PROGS_OBJ) rust.o $(PROGS_DEP) rust.d
+ rm -f $(LIB_DEP) $(LIB_OBJ) lib/user/entry.[do] libc.a
.PHONY: all clean
diff --git a/src/examples/.gitignore b/src/examples/.gitignore
index 850351e..3497886 100644
--- a/src/examples/.gitignore
+++ b/src/examples/.gitignore
@@ -37,3 +37,5 @@ dir_stress
create_file
create_remove_file
*.d
+
+haltrs
diff --git a/src/examples/Makefile b/src/examples/Makefile
index 5b4f6c3..dd777ae 100644
--- a/src/examples/Makefile
+++ b/src/examples/Makefile
@@ -4,11 +4,15 @@ SRCDIR = ..
# To add a new test, put its name on the PROGS list
# and then add a name_SRC line that lists its source files.
PROGS = cat cmp cp echo halt hex-dump ls mcat mcp mkdir pwd rm shell \
- bubsort insult lineup matmult recursor \
- sumargv pfs pfs_reader pfs_writer dummy longrun \
- child parent generic_parent longrun_interactive busy \
- line_echo file_syscall_tests longrun_nowait shellcode \
- crack overflow dir_stress create_file create_remove_file
+ bubsort insult lineup matmult recursor \
+ sumargv pfs pfs_reader pfs_writer dummy longrun \
+ child parent generic_parent longrun_interactive busy \
+ line_echo file_syscall_tests longrun_nowait shellcode \
+ crack overflow dir_stress create_file create_remove_file
+
+PROGS_RS = haltrs
+
+haltrs_SRC = $(SRCDIR)/../halt-rs
# Added test programs
sumargv_SRC = sumargv.c
diff --git a/src/examples/rust.c b/src/examples/rust.c
new file mode 100644
index 0000000..d6dae76
--- /dev/null
+++ b/src/examples/rust.c
@@ -0,0 +1,6 @@
+#include "rust.h"
+
+int main (int argc, char **argv) {
+ entry();
+ return 0;
+}
diff --git a/src/examples/rust.h b/src/examples/rust.h
new file mode 100644
index 0000000..926337e
--- /dev/null
+++ b/src/examples/rust.h
@@ -0,0 +1 @@
+void entry(void);
diff --git a/src/userprog/syscall.c b/src/userprog/syscall.c
index 4d46978..ced27aa 100644
--- a/src/userprog/syscall.c
+++ b/src/userprog/syscall.c
@@ -41,21 +41,21 @@ const int argc[] = {
0
};
-static void
-syscall_handler (struct intr_frame *f)
-{
- int32_t* esp = (int32_t*)f->esp;
-
- switch ( 0 /* retrive syscall number */ )
- {
- default:
- {
- printf ("Executed an unknown system call!\n");
-
- printf ("Stack top + 0: %d\n", esp[0]);
- printf ("Stack top + 1: %d\n", esp[1]);
-
- thread_exit ();
- }
- }
-}
+//static void
+//syscall_handler (struct intr_frame *f)
+//{
+// int32_t* esp = (int32_t*)f->esp;
+//
+// switch ( 0 /* retrive syscall number */ )
+// {
+// default:
+// {
+// printf ("Executed an unknown system call!\n");
+//
+// printf ("Stack top + 0: %d\n", esp[0]);
+// printf ("Stack top + 1: %d\n", esp[1]);
+//
+// thread_exit ();
+// }
+// }
+//}