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

Improve doc and add some simple trivial test in linux-loader #128

Merged
merged 3 commits into from
Aug 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion linux-loader/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
//! Linux LibOS
//! - run process and manage trap/interrupt/syscall
#![no_std]
#![feature(asm)]
#![feature(global_asm)]
#![deny(warnings, unused_must_use)]
#![deny(warnings, unused_must_use, missing_docs)]

extern crate alloc;
#[macro_use]
Expand All @@ -20,6 +22,7 @@ use {
zircon_object::task::*,
};

/// Create and run main Linux process
pub fn run(args: Vec<String>, envs: Vec<String>, rootfs: Arc<dyn FileSystem>) -> Arc<Process> {
let job = Job::root();
let proc = Process::create_linux(&job, rootfs.clone()).unwrap();
Expand All @@ -42,14 +45,25 @@ pub fn run(args: Vec<String>, envs: Vec<String>, rootfs: Arc<dyn FileSystem>) ->
proc
}

/// Run and Manage thread
///
/// loop:
/// - wait for the thread to be ready
/// - get user thread context
/// - enter user mode
/// - handle trap/interrupt/syscall according to the return value
/// - return the context to the user thread
fn spawn(thread: Arc<Thread>) {
let vmtoken = thread.proc().vmar().table_phys();
let future = async move {
loop {
// wait
let mut cx = thread.wait_for_run().await;
// run
trace!("go to user: {:#x?}", cx);
kernel_hal::context_run(&mut cx);
trace!("back from user: {:#x?}", cx);
// handle trap/interrupt/syscall
let mut exit = false;
match cx.trap_num {
0x100 => exit = handle_syscall(&thread, &mut cx.general).await,
Expand Down Expand Up @@ -86,6 +100,7 @@ fn spawn(thread: Arc<Thread>) {
kernel_hal::Thread::spawn(Box::pin(future), vmtoken);
}

/// syscall handler entry: create a struct `syscall: Syscall`, and call `syscall.syscall()`
async fn handle_syscall(thread: &Arc<Thread>, regs: &mut GeneralRegs) -> bool {
trace!("syscall: {:#x?}", regs);
let num = regs.rax as u32;
Expand Down
60 changes: 56 additions & 4 deletions linux-loader/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#![deny(warnings, unused_must_use)]
//! Linux LibOS entrance
#![deny(warnings, unused_must_use, missing_docs)]
#![feature(thread_id_value)]

extern crate log;
Expand All @@ -9,11 +10,14 @@ use std::io::Write;
use std::sync::Arc;
use zircon_object::object::*;

/// main entry
#[async_std::main]
async fn main() {
// init loggger for debug
init_logger();
// init HAL implementation on unix
kernel_hal_unix::init();

// run first process
let args: Vec<_> = std::env::args().skip(1).collect();
let envs = vec!["PATH=/usr/sbin:/usr/bin:/sbin:/bin:/usr/x86_64-alpine-linux-musl/bin".into()];

Expand All @@ -22,6 +26,7 @@ async fn main() {
proc.wait_signal(Signal::PROCESS_TERMINATED).await;
}

/// init the env_logger
fn init_logger() {
env_logger::builder()
.format(|buf, record| {
Expand All @@ -47,19 +52,66 @@ fn init_logger() {
mod tests {
use super::*;

/// test with cmd line
async fn test(cmdline: &str) {
kernel_hal_unix::init();

let args: Vec<String> = cmdline.split(' ').map(|s| s.into()).collect();
let envs = vec![]; // TODO
let envs =
vec!["PATH=/usr/sbin:/usr/bin:/sbin:/bin:/usr/x86_64-alpine-linux-musl/bin".into()]; // TODO
let hostfs = HostFS::new("../rootfs");
let proc = run(args, envs, hostfs);
let proc: Arc<dyn KernelObject> = proc;
proc.wait_signal(Signal::PROCESS_TERMINATED).await;
}

#[async_std::test]
async fn busybox() {
async fn test_busybox() {
test("/bin/busybox").await;
}

#[async_std::test]
async fn test_uname() {
test("/bin/busybox uname -a").await;
}

#[async_std::test]
async fn test_date() {
test("/bin/busybox date").await;
}

#[async_std::test]
async fn test_dir() {
test("/bin/busybox pwd").await;
test("/bin/busybox ls -a").await;
test("/bin/busybox dirname /bin/busybox").await;
}

#[async_std::test]
async fn test_create_remove_dir() {
test("/bin/busybox mkdir test").await;
test("/bin/busybox rmdir test").await;
}

#[async_std::test]
async fn test_readfile() {
test("/bin/busybox cat /etc/profile").await;
}

#[async_std::test]
async fn test_cp_mv() {
test("/bin/busybox cp /etc/hostname /etc/hostname.bak").await;
test("/bin/busybox mv /etc/hostname.bak /etc/hostname.mv").await;
}

#[async_std::test]
async fn test_link() {
test("/bin/busybox ln /etc/hostname /etc/hostname.ln").await;
test("/bin/busybox unlink /etc/hostname.ln").await;
}

#[async_std::test]
async fn test_env() {
test("/bin/busybox env").await;
}
}