add Rust programs. add Makefile

master
WangRunji 6 years ago
parent b7d252e979
commit 86bb44b00d

1
.gitignore vendored

@ -1,2 +1,3 @@
build/ build/
target/
.DS_Store .DS_Store

@ -2,7 +2,10 @@ sudo: false
dist: xenial dist: xenial
language: c language: rust
rust:
- nightly
cache: cache:
directories: directories:
@ -19,6 +22,11 @@ env:
- ARCH="i386" SRC="ucore" - ARCH="i386" SRC="ucore"
# - ARCH="x86_64" SRC="ucore" # - ARCH="x86_64" SRC="ucore"
- ARCH="aarch64" SRC="ucore" - ARCH="aarch64" SRC="ucore"
- ARCH="riscv32" SRC="rust"
- ARCH="riscv64" SRC="rust"
- ARCH="i386" SRC="rust"
- ARCH="x86_64" SRC="rust"
- ARCH="aarch64" SRC="rust"
- ARCH="x86_64" SRC="biscuit" - ARCH="x86_64" SRC="biscuit"
install: install:
@ -48,12 +56,13 @@ install:
- if [ $ARCH = x86_64 ]; then - if [ $ARCH = x86_64 ]; then
if [ $TRAVIS_OS_NAME = osx ]; then if [ $TRAVIS_OS_NAME = osx ]; then
brew tap altkatz/homebrew-gcc_cross_compilers; brew tap altkatz/homebrew-gcc_cross_compilers;
brew install x64-elf-gcc; travis_wait brew install x64-elf-gcc;
fi; fi;
fi fi
before_script:
- rustup component add rust-src
- (test -x $HOME/.cargo/bin/cargo-xbuild || cargo install cargo-xbuild)
script: script:
- cd $SRC - make $SRC arch=$ARCH
- mkdir build && cd build
- cmake -DARCH=$ARCH ..
- make

@ -0,0 +1,66 @@
# arch = {riscv32, riscv64, x86_64, aarch64}
# mode = {debug, release}
arch ?= riscv32
mode ?= debug
out_dir ?= build/$(arch)
out_img ?= build/$(arch).img
rust_src_dir := rust/src/bin
rust_bin_path := rust/target/$(arch)-rcore/$(mode)
rust_bins := $(patsubst $(rust_src_dir)/%.rs, $(rust_bin_path)/%, $(wildcard $(rust_src_dir)/*.rs))
ucore_bin_path := ucore/build/$(arch)
biscuit_bin_path := biscuit/build/$(arch)
rust_build_args := --target targets/$(arch)-rcore.json
cmake_build_args := -DARCH=$(arch)
ifeq ($(mode), release)
rust_build_args += --release
cmake_build_args += -DCMAKE_BUILD_TYPE=Release
endif
.PHONY: all clean build rust ucore biscuit bin
all: build
rust:
@echo Building rust programs
@cd rust && cargo xbuild $(rust_build_args)
@rm -rf $(out_dir)/rust && mkdir -p $(out_dir)/rust
@cp $(rust_bins) $(out_dir)/rust
ucore:
ifneq ($(arch), x86_64)
@echo Building ucore programs
@mkdir -p ucore/build
@cd ucore/build && cmake $(cmake_build_args) .. && make
@rm -rf $(out_dir)/ucore && mkdir -p $(out_dir)/ucore
@cp $(ucore_bin_path)/* $(out_dir)/ucore
endif
biscuit:
ifeq ($(arch), x86_64)
@echo Building biscuit programs
@mkdir -p biscuit/build
@cd biscuit/build && cmake $(cmake_build_args) .. && make
@rm -rf $(out_dir)/biscuit && mkdir -p $(out_dir)/biscuit
@cp $(biscuit_bin_path)/* $(out_dir)/biscuit
endif
build: rust ucore biscuit
sfsimg: $(out_img)
$(out_img): build mksfs
@mksfs zip $(out_dir) $@
mksfs:
ifeq ($(shell which mksfs),)
@cargo install --git https://github.com/wangrunji0408/SimpleFileSystem-Rust --features="std"
endif
clean:
@cd rust && cargo clean
@rm -rf biscuit/build ucore/build
@rm -rf $(out_dir)

@ -6,32 +6,22 @@ User programs for [rCore OS](https://github.com/wangrunji0408/RustOS).
Now it has 2 parts: Now it has 3 parts:
* `ucore`: C-lang, from the original [ucore_os_lab](https://github.com/chyyuu/ucore_os_plus) * `ucore`: C-lang, from the original [ucore_os_lab](https://github.com/chyyuu/ucore_os_plus)
* `biscuit`: C/C++, from [Biscuit](https://github.com/mit-pdos/biscuit), based on a partial libc `litc`. (WIP) * `biscuit`: C/C++, from [Biscuit](https://github.com/mit-pdos/biscuit), based on a partial libc `litc`. (WIP)
* `rust`: Simple no_std Rust programs.
## Build ## Build
For ucore:
```bash ```bash
cd ucore make {ucore,biscuit,rust,all} arch={i386,x86_64,riscv32,riscv64,aarch64}
mkdir build && cd build
cmake -DARCH={i386,x86_64,riscv32,riscv64,aarch64} ..
make
``` ```
For biscuit: Output to `build/$(arch)`
```bash
cd biscuit
mkdir build && cd build
cmake -DARCH=x86_64 ..
make
```
## Notice ## Notice
* The syscall ids have been set compatible with Linux64. * The syscall ids have been set compatible with [Linux64](https://syscalls64.paolostivanin.com).
* So the ucore part can not run on the original ucore. * So the ucore part can not run on the original ucore.

25
rust/Cargo.lock generated

@ -0,0 +1,25 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "linked_list_allocator"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"spin 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rcore-user"
version = "0.1.0"
dependencies = [
"linked_list_allocator 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "spin"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum linked_list_allocator 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "655d57c71827fe0891ce72231b6aa5e14033dae3f604609e6a6f807267c1678d"
"checksum spin 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ceac490aa12c567115b40b7b7fceca03a6c9d53d5defea066123debc83c5dc1f"

@ -0,0 +1,8 @@
[package]
name = "rcore-user"
version = "0.1.0"
authors = ["Runji Wang <wangrunji0408@163.com>"]
edition = "2018"
[dependencies]
linked_list_allocator = "0.6"

@ -0,0 +1,43 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate rcore_user;
macro_rules! color_text {
($text:expr, $color:expr) => {{
format_args!("\x1b[{}m{}\x1b[0m", $color, $text)
}};
}
// IMPORTANT: Must define main() like this
#[no_mangle]
pub fn main() {
println!(
"{}{}{}{}{} {}{}{}{} {}{}{}{}{}{}",
color_text!("H", 31),
color_text!("e", 32),
color_text!("l", 33),
color_text!("l", 34),
color_text!("o", 35),
color_text!("R", 36),
color_text!("u", 37),
color_text!("s", 90),
color_text!("t", 91),
color_text!("u", 92),
color_text!("C", 93),
color_text!("o", 94),
color_text!("r", 95),
color_text!("e", 96),
color_text!("!", 97),
);
let text = "reguler \x1b[4munderline\x1b[24m \x1b[7mreverse\x1b[27m \x1b[9mstrikethrough\x1b[29m";
println!("\x1b[47m{}\x1b[0m", color_text!(text, 30));
for i in 31..38 {
println!("{}", color_text!(text, i));
}
for i in 90..98 {
println!("{}", color_text!(text, i));
}
}

@ -0,0 +1,13 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate rcore_user;
// IMPORTANT: Must define main() like this
#[no_mangle]
pub fn main() {
println!("Hello Rust uCore!");
println!("I am process {}.", rcore_user::syscall::sys_getpid());
println!("hello pass.");
}

@ -0,0 +1,39 @@
#![no_std]
#![no_main]
#![feature(alloc)]
extern crate alloc;
#[macro_use]
extern crate rcore_user;
use alloc::vec::Vec;
use rcore_user::io::get_line;
use rcore_user::syscall::{sys_exec, sys_fork, sys_wait};
// IMPORTANT: Must define main() like this
#[no_mangle]
pub fn main() -> i32 {
println!("Rust user shell");
loop {
print!(">> ");
let cmd = get_line();
// split cmd, make argc & argv
let cmd = cmd.replace(' ', "\0") + "\0";
let ptrs: Vec<*const u8> = cmd.split('\0')
.filter(|s| !s.is_empty()).map(|s| s.as_ptr()).collect();
if ptrs.is_empty() {
continue;
}
let pid = sys_fork();
assert!(pid >= 0);
if pid == 0 {
return sys_exec(ptrs[0], ptrs.len(), ptrs.as_ptr());
} else {
let mut code: i32 = 0;
sys_wait(pid as usize, &mut code);
println!("\n[Process exited with code {}]", code);
}
}
}

@ -0,0 +1,92 @@
use alloc::string::String;
use core::fmt::{self, Write};
use core::option::Option;
use crate::syscall::{sys_read, sys_write};
pub const STDIN: usize = 0;
pub const STDOUT: usize = 1;
#[macro_export]
macro_rules! print {
($($arg:tt)*) => ({
$crate::io::print(format_args!($($arg)*));
});
}
#[macro_export]
macro_rules! println {
($fmt:expr) => (print!(concat!($fmt, "\n")));
($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
}
pub fn print(args: fmt::Arguments) {
StdOut.write_fmt(args).unwrap();
}
pub fn getc() -> Option<u8> {
let mut c = 0u8;
let ret = sys_read(STDIN, &mut c, 1);
match ret {
1 => Some(c),
0 => None,
_ => panic!(),
}
}
pub fn get_line() -> String {
let mut s = String::new();
loop {
let ret = getc();
match ret {
None => return s,
Some(byte) => {
let c = byte as char;
match c {
'\x08' | '\x7f' /* '\b' */ => {
if s.pop().is_some() {
print!("\x08 \x08");
}
}
' '...'\x7e' => {
s.push(c);
print!("{}", c);
}
'\n' | '\r' => {
print!("\n");
return s;
}
_ => {}
}
}
}
}
}
pub fn putc(c: u8) {
sys_write(STDOUT, &c, 1);
}
struct StdOut;
impl fmt::Write for StdOut {
fn write_str(&mut self, s: &str) -> fmt::Result {
if sys_write(STDOUT, s.as_ptr(), s.len()) >= 0 {
Ok(())
} else {
Err(fmt::Error::default())
}
}
}
/* VFS flags */
// TODO: use bitflags
// flags for open: choose one of these
pub const O_RDONLY: usize = 0; // open for reading only
pub const O_WRONLY: usize = 1; // open for writing only
pub const O_RDWR: usize = 2; // open for reading and writing
// then or in any of these:
pub const O_CREAT: usize = 0x00000004; // create file if it does not exist
pub const O_EXCL: usize = 0x00000008; // error if O_CREAT and the file exists
pub const O_TRUNC: usize = 0x00000010; // truncate file upon open
pub const O_APPEND: usize = 0x00000020; // append on each write

@ -0,0 +1,70 @@
use crate::syscall::{sys_close, sys_dup2, sys_exit, sys_open};
use crate::io::{O_RDONLY, O_WRONLY, STDIN, STDOUT};
use crate::ALLOCATOR;
use core::alloc::Layout;
use core::panic::PanicInfo;
#[linkage = "weak"]
#[no_mangle]
fn main() {
panic!("No main() linked");
}
fn initfd(fd2: usize, path: &str, open_flags: usize) -> i32 {
let fd1 = sys_open(path, open_flags);
if fd1 < 0 {
return fd1;
}
let mut ret = fd1;
let fd1 = fd1 as usize;
if fd1 != fd2 {
sys_close(fd2);
ret = sys_dup2(fd1, fd2);
sys_close(fd1);
}
return ret;
}
fn init_heap() {
const HEAP_SIZE: usize = 0x1000;
static mut HEAP: [u8; HEAP_SIZE] = [0; HEAP_SIZE];
unsafe { ALLOCATOR.lock().init(HEAP.as_ptr() as usize, HEAP_SIZE); }
}
#[no_mangle]
pub extern "C" fn _start(_argc: isize, _argv: *const *const u8) -> ! {
let fd = initfd(STDIN, "stdin:", O_RDONLY);
if fd < 0 {
panic!("open <stdin> failed: {}.", fd);
}
let fd = initfd(STDOUT, "stdout:", O_WRONLY);
if fd < 0 {
panic!("open <stdout> failed: {}.", fd);
}
init_heap();
main();
sys_exit(0)
}
#[lang = "eh_personality"]
fn eh_personality() {}
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
let location = info.location().unwrap();
let message = info.message().unwrap();
println!("\n\nPANIC in {} at line {}\n {}", location.file(), location.line(), message);
sys_exit(1)
}
#[lang = "oom"]
fn oom(_: Layout) -> ! {
panic!("out of memory");
}
#[no_mangle]
pub extern "C" fn abort() -> ! {
sys_exit(2)
}

@ -0,0 +1,19 @@
#![no_std]
#![feature(asm)]
#![feature(alloc)]
#![feature(lang_items)]
#![feature(panic_info_message)]
#![feature(linkage)]
#![feature(compiler_builtins_lib)]
extern crate alloc;
#[macro_use]
pub mod io;
pub mod syscall;
pub mod lang_items;
use linked_list_allocator::LockedHeap;
#[global_allocator]
static ALLOCATOR: LockedHeap = LockedHeap::empty();

@ -0,0 +1,133 @@
#[inline(always)]
fn sys_call(syscall_id: SyscallId, arg0: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) -> i32 {
let id = syscall_id as usize;
let ret: i32;
unsafe {
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
asm!("ecall"
: "={x10}" (ret)
: "{x10}" (id), "{x11}" (arg0), "{x12}" (arg1), "{x13}" (arg2), "{x14}" (arg3), "{x15}" (arg4), "{x16}" (arg5)
: "memory"
: "volatile");
#[cfg(target_arch = "x86")]
asm!("int 0x80"
: "={eax}" (ret)
: "{eax}" (id), "{edx}" (arg0), "{ecx}" (arg1), "{ebx}" (arg2), "{edi}" (arg3), "{esi}" (arg4)
: "memory"
: "intel" "volatile");
#[cfg(target_arch = "x86_64")]
asm!("syscall"
: "={rax}" (ret)
: "{rax}" (id), "{rdi}" (arg0), "{rsi}" (arg1), "{rdx}" (arg2), "{rcx}" (arg3), "{r8}" (arg4), "{r9}" (arg5)
: "memory"
: "intel" "volatile");
#[cfg(target_arch = "aarch64")]
asm!("svc 0"
: "={x0}" (ret)
: "{x8}" (id), "{x0}" (arg0), "{x1}" (arg1), "{x2}" (arg2), "{x3}" (arg3), "{x4}" (arg4), "{x5}" (arg5)
: "memory"
: "volatile");
}
ret
}
pub fn sys_exit(code: usize) -> ! {
sys_call(SyscallId::Exit, code, 0, 0, 0, 0, 0);
unreachable!()
}
pub fn sys_exec(name: *const u8, argc: usize, argv: *const *const u8) -> i32 {
sys_call(SyscallId::Exec, name as usize, argc, argv as usize, 0, 0, 0)
}
pub fn sys_write(fd: usize, base: *const u8, len: usize) -> i32 {
sys_call(SyscallId::Write, fd, base as usize, len, 0, 0, 0)
}
pub fn sys_read(fd: usize, base: *mut u8, len: usize) -> i32 {
sys_call(SyscallId::Read, fd, base as usize, len, 0, 0, 0)
}
pub fn sys_open(path: &str, flags: usize) -> i32 {
// UNSAFE: append '\0' to the string
use core::mem::replace;
let end = unsafe { &mut *(path.as_ptr().offset(path.len() as isize) as *mut u8) };
let backup = replace(end, 0);
let ret = sys_call(SyscallId::Open, path.as_ptr() as usize, flags, 0, 0, 0, 0);
*end = backup;
ret
}
pub fn sys_close(fd: usize) -> i32 {
sys_call(SyscallId::Close, fd, 0, 0, 0, 0, 0)
}
pub fn sys_dup2(fd1: usize, fd2: usize) -> i32 {
sys_call(SyscallId::Dup2, fd1, fd2, 0, 0, 0, 0)
}
/// Fork the current process. Return the child's PID.
pub fn sys_fork() -> i32 {
sys_call(SyscallId::Fork, 0, 0, 0, 0, 0, 0)
}
/// Wait the process exit.
/// Return the PID. Store exit code to `code` if it's not null.
pub fn sys_wait(pid: usize, code: *mut i32) -> i32 {
sys_call(SyscallId::Wait, pid, code as usize, 0, 0, 0, 0)
}
pub fn sys_yield() -> i32 {
sys_call(SyscallId::Yield, 0, 0, 0, 0, 0, 0)
}
/// Kill the process
pub fn sys_kill(pid: usize) -> i32 {
sys_call(SyscallId::Kill, pid, 0, 0, 0, 0, 0)
}
/// Get the current process id
pub fn sys_getpid() -> i32 {
sys_call(SyscallId::GetPid, 0, 0, 0, 0, 0, 0)
}
pub fn sys_sleep(time: usize) -> i32 {
sys_call(SyscallId::Sleep, time, 0, 0, 0, 0, 0)
}
pub fn sys_get_time() -> i32 {
sys_call(SyscallId::GetTime, 0, 0, 0, 0, 0, 0)
}
pub fn sys_set_priority(priority: usize) -> i32 {
sys_call(SyscallId::SetPriority, priority, 0, 0, 0, 0, 0)
}
#[allow(dead_code)]
enum SyscallId {
Exit = 60,
Fork = 57,
Wait = 61,
Exec = 59,
Clone = 56,
Yield = 24,
Sleep = 35,
Kill = 62,
GetTime = 96,
GetPid = 39,
Mmap = 9,
Munmap = 11,
Open = 2,
Close = 3,
Read = 0,
Write = 1,
Seek = 8,
Fstat = 4,
Fsync = 74,
GetCwd = 79,
GetDirEntry = 78,
Dup2 = 33,
SetPriority = 141,
}

@ -0,0 +1,35 @@
{
"abi-blacklist": [
"stdcall",
"fastcall",
"vectorcall",
"thiscall",
"win64",
"sysv64"
],
"arch": "aarch64",
"data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
"executables": true,
"linker": "rust-lld",
"linker-flavor": "ld.lld",
"linker-is-gnu": true,
"pre-link-args": {
"ld.lld": [
"--image-base=0xffff000000000000"
]
},
"llvm-target": "aarch64-unknown-none",
"no-compiler-rt": true,
"features": "+a53,+strict-align,-neon",
"max-atomic-width": 128,
"os": "none",
"panic": "abort",
"panic-strategy": "abort",
"relocation-model": "static",
"position-independent-executables": true,
"target-c-int-width": "32",
"target-endian": "little",
"target-pointer-width": "64",
"target-family": "unix",
"disable-redzone": true
}

@ -0,0 +1,16 @@
{
"arch": "x86",
"cpu": "i386",
"data-layout": "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128",
"executables": true,
"linker-flavor": "ld.lld",
"linker": "rust-lld",
"llvm-target": "i386",
"max-atomic-width": 64,
"os": "none",
"panic-strategy": "abort",
"target-c-int-width": "32",
"target-endian": "little",
"target-pointer-width": "32",
"features": "-mmx,-sse,+soft-float"
}

@ -0,0 +1,30 @@
{
"llvm-target": "riscv32",
"data-layout": "e-m:e-p:32:32-i64:64-n32-S128",
"target-endian": "little",
"target-pointer-width": "32",
"target-c-int-width": "32",
"os": "none",
"arch": "riscv32",
"cpu": "generic-rv32",
"features": "+m,+a,+c",
"max-atomic-width": "32",
"linker": "rust-lld",
"linker-flavor": "ld.lld",
"executables": true,
"panic-strategy": "abort",
"relocation-model": "static",
"abi-blacklist": [
"cdecl",
"stdcall",
"fastcall",
"vectorcall",
"thiscall",
"aapcs",
"win64",
"sysv64",
"ptx-kernel",
"msp430-interrupt",
"x86-interrupt"
]
}

@ -0,0 +1,30 @@
{
"llvm-target": "riscv64",
"data-layout": "e-m:e-p:64:64-i64:64-n64-S128",
"target-endian": "little",
"target-pointer-width": "64",
"target-c-int-width": "32",
"os": "none",
"arch": "riscv64",
"cpu": "generic-rv64",
"features": "+m,+a,+c",
"max-atomic-width": "64",
"linker": "rust-lld",
"linker-flavor": "ld.lld",
"executables": true,
"panic-strategy": "abort",
"relocation-model": "static",
"abi-blacklist": [
"cdecl",
"stdcall",
"fastcall",
"vectorcall",
"thiscall",
"aapcs",
"win64",
"sysv64",
"ptx-kernel",
"msp430-interrupt",
"x86-interrupt"
]
}

@ -0,0 +1,15 @@
{
"llvm-target": "x86_64-unknown-none",
"data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
"arch": "x86_64",
"target-endian": "little",
"target-pointer-width": "64",
"target-c-int-width": "32",
"os": "none",
"executables": true,
"linker": "rust-lld",
"linker-flavor": "ld.lld",
"panic-strategy": "abort",
"disable-redzone": true,
"features": "-mmx,-sse,+soft-float"
}
Loading…
Cancel
Save