Skip to content

Commit

Permalink
Merge pull request #68 from Sssssaltyfish/rv-musl
Browse files Browse the repository at this point in the history
Implemented riscv64 syscall support by modifying source code of musl
  • Loading branch information
coolyjg authored May 6, 2024
2 parents 1529b73 + d2926bf commit 3c62d2d
Show file tree
Hide file tree
Showing 148 changed files with 3,523 additions and 1,633 deletions.
20 changes: 20 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 0 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ members = [
"crates/axfs_vfs",
"crates/axio",
"crates/capability",
"crates/crate_interface",
"crates/driver_9p",
"crates/driver_block",
"crates/driver_common",
Expand All @@ -22,11 +21,8 @@ members = [
"crates/driver_virtio",
"crates/dtb",
"crates/flatten_objects",
"crates/handler_table",
"crates/kernel_guard",
"crates/lazy_init",
"crates/linked_list",
"crates/memory_addr",
"crates/page_table",
"crates/page_table_entry",
"crates/percpu",
Expand Down Expand Up @@ -71,7 +67,3 @@ lto = true
[profile.reldebug]
inherits = "release"
debug = true


[patch.crates-io]
crate_interface = { path = "crates/crate_interface" }
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ RuxOS was inspired by [Unikraft](https://github.com/unikraft/unikraft) and [Arce
* [x] SMP scheduling with single run queue
* [x] File system
* [x] Compatible with Linux apps
* [x] Dynamically loading apps
* [ ] Interrupt driven device I/O
* [ ] Async I/O

Expand Down Expand Up @@ -63,6 +64,9 @@ The currently supported applications (Rust), as well as their dependent modules
| [iperf](apps/c/iperf/) | alloc, paging, net, fs, blkfs, select, fp_simd | A network performance test tool |
| [redis](apps/c/redis/) | alloc, paging, fp_simd, irq, multitask, fs, blkfs, net, pipe, epoll, poll, virtio-9p, rtc | A Redis server on Ruxos |
| [sqlite3](apps/c/sqlite3/) | alloc, paging, fs, fp_simd, blkfs | A simple test for Sqlite3 API |
| [cpp](apps/c/cpp/) | alloc, paging, irq, multitask, fs, random-hw | C++ benchmark |
| [dl](apps/c/dl/) | paging, alloc, irq, musl, multitask, fs, pipe, poll, rtc, signal, virtio-9p | An example for dynamically loading apps |


## Build & Run

Expand Down
1 change: 1 addition & 0 deletions api/arceos_api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ default = []
irq = ["ruxfeat/irq"]
rtc = ["ruxfeat/rtc"]
alloc = ["dep:axalloc", "ruxfeat/alloc"]
paging = ["alloc", "ruxfeat/paging"]
multitask = ["ruxtask/multitask", "ruxfeat/multitask"]
fs = ["dep:ruxfs", "ruxfeat/fs"]
net = ["dep:axnet", "ruxfeat/net"]
Expand Down
6 changes: 3 additions & 3 deletions api/ruxfeat/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,16 @@ sched_rr = ["ruxtask/sched_rr", "irq"]
sched_cfs = ["ruxtask/sched_cfs", "irq"]

# File system
fs = ["alloc", "paging", "dep:ruxfs", "ruxruntime/fs"] # TODO: try to remove "paging"
fs = ["alloc", "dep:ruxfs", "ruxruntime/fs"]
blkfs = ["ruxdriver/virtio-blk", "ruxruntime/blkfs"]
myfs = ["ruxfs?/myfs"]
9pfs = []

# Networking
net = ["alloc", "paging", "ruxdriver/virtio-net", "dep:axnet", "ruxruntime/net"]
net = ["alloc", "ruxdriver/virtio-net", "dep:axnet", "ruxruntime/net"]

# Display
display = ["alloc", "paging", "ruxdriver/virtio-gpu", "dep:ruxdisplay", "ruxruntime/display"]
display = ["alloc", "ruxdriver/virtio-gpu", "dep:ruxdisplay", "ruxruntime/display"]

# 9P
virtio-9p = ["9pfs", "ruxdriver/virtio-9p", "rux9p/virtio-9p", "ruxruntime/virtio-9p"]
Expand Down
10 changes: 8 additions & 2 deletions api/ruxos_posix_api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ authors = [
"Shiping Yuan <robert_yuan@pku.edu.com>",
]
description = "POSIX-compatible APIs for Ruxos modules"
license = "GPL-3.0-or-later OR Apache-2.0"
license = "Mulan PSL v2"
repository = "https://github.com/syswonder/ruxos/tree/main/api/ruxos_posix_api"

[features]
default = []

smp = ["ruxfeat/smp"]
alloc = ["dep:axalloc", "ruxfeat/alloc"]
paging = ["alloc", "ruxfeat/paging"]
multitask = ["ruxfeat/multitask", "ruxtask/multitask", "dep:ruxfutex"]
fd = ["alloc"]
fs = ["dep:ruxfs", "ruxfeat/fs", "fd"]
Expand Down Expand Up @@ -51,12 +52,17 @@ axnet = { path = "../../modules/axnet", optional = true }
# Other crates
axio = { path = "../../crates/axio" }
axerrno = { path = "../../crates/axerrno" }
memory_addr = { path = "../../crates/memory_addr" }
memory_addr = "0.1.0"
static_assertions = "1.1.0"
spin = { version = "0.9" }
spinlock = { path = "../../crates/spinlock" }
lazy_static = { version = "1.4", features = ["spin_no_std"] }
flatten_objects = { path = "../../crates/flatten_objects" }
page_table = { path = "../../crates/page_table" }
crate_interface = "0.1.1"

cfg-if = "1.0"
elf = { version = "0.7", default-features = false }
bitflags = "2.2"

[build-dependencies]
Expand Down
5 changes: 4 additions & 1 deletion api/ruxos_posix_api/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,10 @@ typedef struct {{
"EINVAL",
"CLONE_.*",
"AT_.*",
"MAP_FAILED",
"MAP_.+",
"PROT_.+",
"MS_.+",
"MREMAP_.+",
];

#[derive(Debug)]
Expand Down
42 changes: 42 additions & 0 deletions api/ruxos_posix_api/src/imp/cap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use core::ffi::c_int;

#[derive(Debug, Clone, Copy)]
struct UserCapHeader {
/// Linux Cap Version:
/// Version1 = 0x19980330,
/// Version2 = 0x20071026,
/// Version3 = 0x20080522,
version: u32,
pid: i32,
}

/// The effective, permitted, and inheritable fields are bit masks of the capabilities.
/// Note that the CAP_* values are bit indexes and need to be bit-shifted before ORing into the bit fields.
#[derive(Debug, Clone, Copy)]
struct UserCapData {
effective: u32,
permitted: u32,
inheritable: u32,
}

/// get thread capabilities. specific to Linux.
pub fn sys_cap_get(cap_user_header: usize, cap_user_data: usize) -> c_int {
let hdrp = cap_user_header as *const UserCapHeader;
let datap = cap_user_data as *mut UserCapData;
unsafe {
debug!(
"sys_cap_get <= pid {:?}, version {:x?} ",
(*hdrp).pid,
(*hdrp).version
);
}
syscall_body!(sys_cap_get, {
unsafe {
// allow all
(*datap).effective = u32::MAX;
(*datap).inheritable = u32::MAX;
(*datap).permitted = u32::MAX;
};
Ok(0)
})
}
41 changes: 41 additions & 0 deletions api/ruxos_posix_api/src/imp/execve/auxv.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#![allow(unused)]

pub const AT_NULL: usize = 0;
pub const AT_IGNORE: usize = 1;

pub const AT_EXECFD: usize = 2;

/// The address of the program headers of the executable.
pub const AT_PHDR: usize = 3;

pub const AT_PHENT: usize = 4;
pub const AT_PHNUM: usize = 5;
pub const AT_PAGESZ: usize = 6;

/// The base address of the program interpreter (usually, the dynamic linker).
pub const AT_BASE: usize = 7;

pub const AT_FLAGS: usize = 8;
pub const AT_ENTRY: usize = 9;
pub const AT_NOTELF: usize = 10;
pub const AT_UID: usize = 11;
pub const AT_EUID: usize = 12;
pub const AT_GID: usize = 13;
pub const AT_EGID: usize = 14;
pub const AT_PLATFORM: usize = 15;
pub const AT_HWCAP: usize = 16;
pub const AT_CLKTCK: usize = 17;
pub const AT_DCACHEBSIZE: usize = 19;
pub const AT_ICACHEBSIZE: usize = 20;
pub const AT_UCACHEBSIZE: usize = 21;
pub const AT_SECURE: usize = 23;
pub const AT_RANDOM: usize = 25;

/// A pointer to a string containing the pathname used to execute the program.
pub const AT_EXECFN: usize = 31;

/// The address of a page containing the vDSO that the kernel creates
pub const AT_SYSINFO_EHDR: usize = 33;

/// The entry point to the system call function in the vDSO. Not present/needed on all architectures (e.g., absent on x86-64).
pub const AT_SYSINFO: usize = 32;
106 changes: 106 additions & 0 deletions api/ruxos_posix_api/src/imp/execve/load_elf.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
use crate::{ctypes::kstat, *};
use alloc::{vec, vec::Vec};
use core::ptr::null_mut;

#[derive(Debug)]
pub struct ElfProg {
pub base: usize,
pub entry: usize,
pub interp_path: Vec<u8>,
pub phent: usize,
pub phnum: usize,
pub phdr: usize,
}

impl ElfProg {
/// read elf from `path`, and copy LOAD segments to a alloacated memory
///
/// and load interp, if needed.
pub fn new(filepath: &str) -> Self {
debug!("sys_execve: new elf prog: {filepath}");

// open file
let fd = sys_open(filepath.as_ptr() as _, ctypes::O_RDWR as _, 0);

// get file size
let mut buf = ctypes::kstat {
..Default::default()
};
sys_fstat(fd, &mut buf as *const kstat as *mut _);
let filesize = buf.st_size as usize;

// read file
let mut file = vec![0u8; filesize];
sys_read(fd, file.as_mut_ptr() as *mut _, filesize);
debug!("sys_execve: read file size 0x{filesize:x}");
sys_close(fd);

// parse elf
let file = elf::ElfBytes::<elf::endian::AnyEndian>::minimal_parse(&file)
.expect("parse ELF failed");

// get program's LOAD mem size
let mut min_addr = 0;
let mut max_addr = 0;
let segs = file.segments().unwrap();
for seg in segs {
if seg.p_type == elf::abi::PT_LOAD {
min_addr = min_addr.min(seg.p_vaddr);
max_addr = max_addr.max(seg.p_vaddr + seg.p_memsz);
}
}
let msize = (max_addr - min_addr) as usize;

// alloc memory for LOAD
let prot = ctypes::PROT_WRITE | ctypes::PROT_READ | ctypes::PROT_EXEC;
let flags = ctypes::MAP_ANONYMOUS | ctypes::MAP_PRIVATE;
let base = crate::sys_mmap(null_mut(), msize, prot as _, flags as _, -1, 0) as usize;

// copy LOAD segments
for seg in segs {
if seg.p_type == elf::abi::PT_LOAD {
let data = file.segment_data(&seg).unwrap();
let dst = (seg.p_vaddr as usize + base) as *mut u8;
unsafe { dst.copy_from_nonoverlapping(data.as_ptr(), data.len()) };
}
}

// phdr
let phdr = base + file.ehdr.e_phoff as usize;

// get entry
let entry = file.ehdr.e_entry as usize + base;

// parse interpreter
let mut interp_path = vec![];
for seg in file.segments().unwrap() {
if seg.p_type == elf::abi::PT_INTERP {
let data = file.segment_data(&seg).unwrap().to_vec();
interp_path = data;
break;
}
}

// get address of .text for debugging
let text_section_addr = base
+ file
.section_header_by_name(".text")
.unwrap()
.unwrap()
.sh_offset as usize;
debug!(
"sys_execve: loaded ELF in 0x{:x}, .text is 0x{:x}",
base, text_section_addr
);

// create retval
Self {
base,
entry,
interp_path,
phent: file.ehdr.e_phentsize as usize,
phnum: file.ehdr.e_phnum as usize,
phdr,
}
}
}
Loading

0 comments on commit 3c62d2d

Please sign in to comment.