diff --git a/.travis.yml b/.travis.yml index 493c530f..37a4f6ac 100644 --- a/.travis.yml +++ b/.travis.yml @@ -83,3 +83,4 @@ before_script: script: - cd user && make sfsimg arch=$ARCH && cd .. - cd kernel && make build arch=$ARCH $OPTS && cd .. + - cd tests && ./test.sh && cd .. diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 0bfebb08..aa606426 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -26,6 +26,8 @@ board_raspi3 = ["bcm2837", "link_user"] raspi3_use_generic_timer = ["bcm2837/use_generic_timer"] # Hard link user program link_user = [] +# Run cmdline instead of user shell, useful for automatic testing +run_cmdline = [] [profile.dev] # MUST >= 1 : Enable RVO to avoid stack overflow diff --git a/kernel/Makefile b/kernel/Makefile index a9636442..d00b0ddd 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -2,6 +2,12 @@ # make build Build # make run Build and run in QEMU # make justrun Run the last build +# make runnet Build and run in QEMU with nic +# make justrunnet Run the last build with nic +# make runui Build and run in QEMU with gui +# make justrunui Run the last build with gui +# make runtest Build and run in QEMU with specified program +# make justruntest Run the last build with specified program # make doc Generate docs # make asm Open the deassemble file of the last build # make header Open 'objdump -h' of the last build @@ -19,7 +25,8 @@ # board = none Running on QEMU # | u540 Only available on riscv64, run on HiFive U540, use Sv39 # | raspi3 Only available on aarch64, run on Raspberry Pi 3 Model B/B+ -# pci_passthru Only available on x86_64, passthrough the specified PCI device +# pci_passthru = 0000:00:00.1 Only available on x86_64, passthrough the specified PCI device +# init = /bin/ls Only available on riscv64, run specified program instead of user shell arch ?= riscv64 board ?= none @@ -28,6 +35,7 @@ LOG ?= debug graphic ?= off smp ?= 4 pci_passthru ?= +init ?= target := $(arch) build_path := target/$(target)/$(mode) @@ -54,7 +62,8 @@ endif ### qemu options ### qemu_opts := \ - -smp cores=$(smp) + -smp cores=$(smp) \ + -append "test=biscuit/fork" qemu_net_opts := \ -netdev type=tap,id=net0,script=no,downscript=no @@ -112,6 +121,10 @@ ifneq ($(graphic), on) features += nographic endif +ifneq ($(init), ) +features += run_cmdline +endif + ifeq ($(board), raspi3) # qemu only has generic timer # TODO: configure system/generic timer automatically @@ -162,7 +175,7 @@ gdb := $(prefix)gdb strip := $(prefix)strip export CC = $(cc) -.PHONY: all clean run build asm doc justrun debug kernel sfsimg install runnet +.PHONY: all clean build asm doc debug kernel sfsimg install run justrun runnet justrunnet runui justrunui runtest justruntest all: kernel @@ -177,6 +190,7 @@ doc: run: build justrun runnet: build justrunnet runui: build justrunui +runtest: build justruntest justrun: @qemu-system-$(arch) $(qemu_opts) @@ -189,6 +203,9 @@ justrunui: build -device virtio-gpu-device \ -device virtio-mouse-device +justruntest: build + @qemu-system-$(arch) $(qemu_opts) --append $(init) -serial file:../tests/stdout -monitor null + debug: $(kernel) $(kernel_img) @qemu-system-$(arch) $(qemu_opts) -s -S & @sleep 1 diff --git a/kernel/src/drivers/device_tree.rs b/kernel/src/drivers/device_tree.rs index 154e0616..f2e72553 100644 --- a/kernel/src/drivers/device_tree.rs +++ b/kernel/src/drivers/device_tree.rs @@ -1,8 +1,10 @@ use core::slice; +use alloc::string::String; use device_tree::{DeviceTree, Node}; use super::bus::virtio_mmio::virtio_probe; +use super::CMDLINE; const DEVICE_TREE_MAGIC: u32 = 0xd00dfeed; @@ -13,6 +15,12 @@ fn walk_dt_node(dt: &Node) { virtio_probe(dt); } } + if let Ok(bootargs) = dt.prop_str("bootargs") { + if bootargs.len() > 0 { + info!("Kernel cmdline: {}", bootargs); + *CMDLINE.write() = String::from(bootargs); + } + } for child in dt.children.iter() { walk_dt_node(child); } diff --git a/kernel/src/drivers/mod.rs b/kernel/src/drivers/mod.rs index da64652f..243d240f 100644 --- a/kernel/src/drivers/mod.rs +++ b/kernel/src/drivers/mod.rs @@ -86,3 +86,8 @@ pub fn init(dtb: usize) { pub fn init() { bus::pci::init(); } + +lazy_static! { + // Write only once at boot + pub static ref CMDLINE: RwLock = RwLock::new(String::new()); +} \ No newline at end of file diff --git a/kernel/src/shell.rs b/kernel/src/shell.rs index 5a04e5f1..0402a3e6 100644 --- a/kernel/src/shell.rs +++ b/kernel/src/shell.rs @@ -4,7 +4,9 @@ use alloc::string::String; use alloc::vec::Vec; use crate::fs::{ROOT_INODE, INodeExt}; use crate::process::*; +use crate::drivers::CMDLINE; +#[cfg(not(feature = "run_cmdline"))] pub fn run_user_shell() { if let Ok(inode) = ROOT_INODE.lookup("rust/sh") { let data = inode.read_as_vec().unwrap(); @@ -14,6 +16,14 @@ pub fn run_user_shell() { } } +#[cfg(feature = "run_cmdline")] +pub fn run_user_shell() { + let cmdline = CMDLINE.read(); + let inode = ROOT_INODE.lookup(&cmdline).unwrap(); + let data = inode.read_as_vec().unwrap(); + processor().manager().add(Thread::new_user(data.as_slice(), cmdline.split(' '))); +} + pub extern fn shell(_arg: usize) -> ! { let files = ROOT_INODE.list().unwrap(); println!("Available programs: {:?}", files); diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 00000000..faa3a15c --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1 @@ +stdout diff --git a/tests/fork.exp b/tests/fork.exp deleted file mode 100644 index d30cfa2b..00000000 --- a/tests/fork.exp +++ /dev/null @@ -1,17 +0,0 @@ -set timeout -1 -set send_slow {1 .1} -proc send {ignore arg} { - sleep .1 - exp_send -s -- $arg -} - -cd ../kernel -spawn make run arch=x86_64 -sleep 2 -expect ">>" -sleep 2 -send -- "biscuit/fork\r" -sleep 5 -expect "hello from 100" -expect "parent done!" -send -- "busybox halt -f\r" diff --git a/tests/hello_rust.cmd b/tests/hello_rust.cmd new file mode 100644 index 00000000..9485a446 --- /dev/null +++ b/tests/hello_rust.cmd @@ -0,0 +1 @@ +rust/hello_rust diff --git a/tests/hello_rust.out b/tests/hello_rust.out new file mode 100644 index 00000000..beaee7a3 --- /dev/null +++ b/tests/hello_rust.out @@ -0,0 +1,3 @@ +Hello Rust uCore! +I am process 0. +hello pass. diff --git a/tests/killtest.exp b/tests/killtest.exp deleted file mode 100644 index c9030364..00000000 --- a/tests/killtest.exp +++ /dev/null @@ -1,16 +0,0 @@ -set timeout -1 -set send_slow {1 .1} -proc send {ignore arg} { - sleep .1 - exp_send -s -- $arg -} - -cd ../kernel -spawn make run arch=x86_64 -sleep 2 -expect ">>" -sleep 2 -send -- "biscuit/killtest\r" -sleep 2 -expect "success" -send -- "busybox halt -f\r" diff --git a/tests/test.sh b/tests/test.sh index 455c8309..8ffc9d39 100755 --- a/tests/test.sh +++ b/tests/test.sh @@ -1,6 +1,17 @@ #!/bin/bash -for f in *.exp +for f in *.cmd do - echo run $f - timeout 30s expect $f + echo testing $f begin + ( + cd ../kernel + exec timeout 10s make runtest arch=riscv64 init=$(cat ../tests/$f) + ) & + + pid=$! + + wait $pid + + diff -I 'bbl loader' -I 'Hello RISCV! in hart' -u ${f%.cmd}.out stdout || { echo 'testing failed for' $f; exit 1; } + + echo testing $f pass done diff --git a/user b/user index e60682ae..586e682f 160000 --- a/user +++ b/user @@ -1 +1 @@ -Subproject commit e60682ae3241dd6c18798a411051f7209d60a9ba +Subproject commit 586e682f064ca124a353d992cdf365e0d8234cb7