Skip to content

Commit

Permalink
Merge pull request #120 from Freax13/feature/custom-test-framework
Browse files Browse the repository at this point in the history
run tests inside SVSM
  • Loading branch information
joergroedel committed Oct 23, 2023
2 parents 0784379 + 845ec96 commit 6138015
Show file tree
Hide file tree
Showing 18 changed files with 257 additions and 15 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
# ld to work, so build all the objects without performing the
# final linking step.
- name: Build
run: make FEATURES="default,enable-gdb" stage1/stage1.o stage1/reset.o
run: make FEATURES="default,enable-gdb" stage1/kernel.elf stage1/stage1.o stage1/reset.o

- name: Run tests
run: make test
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ target/
gen_meta
stage1/stage1
print-meta
cbit
.idea/
5 changes: 5 additions & 0 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ intrusive-collections = "0.9.6"
log = { version = "0.4.17", features = ["max_level_info", "release_max_level_info"] }
packit = { git = "https://github.com/coconut-svsm/packit", version = "0.1.0" }

[build-dependencies]
[target."x86_64-unknown-none".dev-dependencies]
test = { version = "0.1.0", path = "test" }

[features]
default = ["enable-stacktrace"]
Expand Down
6 changes: 6 additions & 0 deletions INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,12 @@ The project also contains a number of unit-tests which can be run by
$ make test
```

Unit tests can be run inside the SVSM by

```
$ QEMU=/path/to/qemu OVMF=/path/to/firmware/ make test-in-svsm
```

Putting it all together
-----------------------

Expand Down
23 changes: 18 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,38 @@ FEATURES ?= "default"
CARGO_ARGS = --features ${FEATURES}

ifdef RELEASE
TARGET_PATH="release"
TARGET_PATH=release
CARGO_ARGS += --release
else
TARGET_PATH="debug"
TARGET_PATH=debug
endif

STAGE2_ELF = "target/x86_64-unknown-none/${TARGET_PATH}/stage2"
KERNEL_ELF = "target/x86_64-unknown-none/${TARGET_PATH}/svsm"
TEST_KERNEL_ELF = target/x86_64-unknown-none/${TARGET_PATH}/svsm-test
FS_FILE ?= none

C_BIT_POS ?= 51

STAGE1_OBJS = stage1/stage1.o stage1/reset.o

all: svsm.bin
all: stage1/kernel.elf svsm.bin

test:
cargo test --target=x86_64-unknown-linux-gnu

test-in-svsm: utils/cbit stage1/test-kernel.elf svsm.bin
./scripts/test-in-svsm.sh

utils/gen_meta: utils/gen_meta.c
cc -O3 -Wall -o $@ $<

utils/print-meta: utils/print-meta.c
cc -O3 -Wall -o $@ $<

utils/cbit: utils/cbit.c
cc -O3 -Wall -o $@ $<

stage1/meta.bin: utils/gen_meta utils/print-meta
./utils/gen_meta $@

Expand All @@ -36,13 +45,17 @@ stage1/kernel.elf:
cargo build ${CARGO_ARGS} --bin svsm
objcopy -O elf64-x86-64 --strip-unneeded ${KERNEL_ELF} $@

stage1/test-kernel.elf:
LINK_TEST=1 cargo +nightly test --config 'target.x86_64-unknown-none.runner=["sh", "-c", "cp $$0 ${TEST_KERNEL_ELF}"]'
objcopy -O elf64-x86-64 --strip-unneeded ${TEST_KERNEL_ELF} stage1/kernel.elf

stage1/svsm-fs.bin:
ifneq ($(FS_FILE), none)
cp -f $(FS_FILE) stage1/svsm-fs.bin
endif
touch stage1/svsm-fs.bin

stage1/stage1.o: stage1/stage1.S stage1/stage2.bin stage1/kernel.elf stage1/svsm-fs.bin
stage1/stage1.o: stage1/stage1.S stage1/stage2.bin stage1/svsm-fs.bin
cc -c -o $@ stage1/stage1.S

stage1/reset.o: stage1/reset.S stage1/meta.bin
Expand All @@ -57,4 +70,4 @@ clean:
cargo clean
rm -f stage1/stage2.bin svsm.bin stage1/meta.bin stage1/kernel.elf stage1/stage1 stage1/svsm-fs.bin ${STAGE1_OBJS} utils/gen_meta utils/print-meta

.PHONY: stage1/stage2.bin stage1/kernel.elf svsm.bin clean stage1/svsm-fs.bin
.PHONY: stage1/stage2.bin stage1/kernel.elf stage1/test-kernel.elf svsm.bin clean stage1/svsm-fs.bin test test-in-svsm
11 changes: 11 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,15 @@ fn main() {
println!("cargo:rustc-link-arg-bin=svsm=--no-relax");
println!("cargo:rustc-link-arg-bin=svsm=-Tsvsm.lds");
println!("cargo:rustc-link-arg-bin=svsm=-no-pie");

// Extra linker args for tests.
println!("cargo:rerun-if-env-changed=LINK_TEST");
if std::env::var("LINK_TEST").is_ok() {
println!("cargo:rustc-cfg=test_in_svsm");
println!("cargo:rustc-link-arg=-nostdlib");
println!("cargo:rustc-link-arg=--build-id=none");
println!("cargo:rustc-link-arg=--no-relax");
println!("cargo:rustc-link-arg=-Tsvsm.lds");
println!("cargo:rustc-link-arg=-no-pie");
}
}
34 changes: 34 additions & 0 deletions scripts/test-in-svsm.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/bin/bash
#

set -e

if [ "$QEMU" == "" ]; then
echo "Set QEMU environment variable to QEMU installation path" && exit 1
fi
if [ "$OVMF_PATH" == "" ]; then
echo "Set OVMF_PATH environment variable to a folder containing OVMF_CODE.fd and OVMF_VARS.fd" && exit 1
fi
if [ "$SUDO" != "" ]; then
SUDO_CMD="sudo"
else
SUDO_CMD=""
fi

C_BIT_POS=`utils/cbit`

$SUDO_CMD $QEMU \
-enable-kvm \
-cpu EPYC-v4 \
-machine q35,confidential-guest-support=sev0,memory-backend=ram1,kvm-type=protected \
-object memory-backend-memfd-private,id=ram1,size=1G,share=true \
-object sev-snp-guest,id=sev0,cbitpos=$C_BIT_POS,reduced-phys-bits=1,svsm=on \
-smp 8 \
-no-reboot \
-drive if=pflash,format=raw,unit=0,file=$OVMF_PATH/OVMF_CODE.fd,readonly=on \
-drive if=pflash,format=raw,unit=1,file=$OVMF_PATH/OVMF_VARS.fd,snapshot=on \
-drive if=pflash,format=raw,unit=2,file=./svsm.bin,readonly=on \
-nographic \
-monitor none \
-serial stdio \
-device isa-debug-exit,iobase=0xf4,iosize=0x04 || true
6 changes: 6 additions & 0 deletions src/fs/filesystem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ mod tests {
use crate::mm::alloc::{TestRootMem, DEFAULT_TEST_MEMORY_SIZE};

#[test]
#[cfg_attr(test_in_svsm, ignore = "FIXME")]
fn create_dir() {
let _test_mem = TestRootMem::setup(DEFAULT_TEST_MEMORY_SIZE);
initialize_fs();
Expand All @@ -300,6 +301,7 @@ mod tests {
}

#[test]
#[cfg_attr(test_in_svsm, ignore = "FIXME")]
fn create_and_unlink_file() {
let _test_mem = TestRootMem::setup(DEFAULT_TEST_MEMORY_SIZE);
initialize_fs();
Expand Down Expand Up @@ -330,6 +332,7 @@ mod tests {
}

#[test]
#[cfg_attr(test_in_svsm, ignore = "FIXME")]
fn create_sub_dir() {
let _test_mem = TestRootMem::setup(DEFAULT_TEST_MEMORY_SIZE);
initialize_fs();
Expand Down Expand Up @@ -358,6 +361,7 @@ mod tests {
}

#[test]
#[cfg_attr(test_in_svsm, ignore = "FIXME")]
fn test_unlink() {
let _test_mem = TestRootMem::setup(DEFAULT_TEST_MEMORY_SIZE);
initialize_fs();
Expand Down Expand Up @@ -387,6 +391,7 @@ mod tests {
}

#[test]
#[cfg_attr(test_in_svsm, ignore = "FIXME")]
fn test_open_read_write_seek() {
let _test_mem = TestRootMem::setup(DEFAULT_TEST_MEMORY_SIZE);
initialize_fs();
Expand Down Expand Up @@ -438,6 +443,7 @@ mod tests {
}

#[test]
#[cfg_attr(test_in_svsm, ignore = "FIXME")]
fn test_multiple_file_handles() {
let _test_mem = TestRootMem::setup(DEFAULT_TEST_MEMORY_SIZE);
initialize_fs();
Expand Down
1 change: 1 addition & 0 deletions src/fs/ramfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ mod tests {
use crate::mm::alloc::{TestRootMem, DEFAULT_TEST_MEMORY_SIZE};

#[test]
#[cfg_attr(test_in_svsm, ignore = "FIXME")]
fn test_ramfs_file_read_write() {
let _test_mem = TestRootMem::setup(DEFAULT_TEST_MEMORY_SIZE);

Expand Down
16 changes: 16 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
// Author: Nicolai Stange <nstange@suse.de>

#![no_std]
#![cfg_attr(all(test, test_in_svsm), no_main)]
#![cfg_attr(all(test, test_in_svsm), feature(custom_test_frameworks))]
#![cfg_attr(all(test, test_in_svsm), test_runner(crate::testing::svsm_test_runner))]
#![cfg_attr(all(test, test_in_svsm), reexport_test_harness_main = "test_main")]

pub mod acpi;
pub mod address;
Expand Down Expand Up @@ -33,3 +37,15 @@ pub mod utils;

#[test]
fn test_nop() {}

// When running tests inside the SVSM:
// Build the kernel entrypoint.
#[cfg(all(test, test_in_svsm))]
#[path = "svsm.rs"]
pub mod svsm_bin;
// The kernel expects to access this crate as svsm, so reexport.
#[cfg(all(test, test_in_svsm))]
extern crate self as svsm;
// Include a module containing the test runner.
#[cfg(all(test, test_in_svsm))]
pub mod testing;
12 changes: 6 additions & 6 deletions src/mm/address_space.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
//
// Author: Joerg Roedel <jroedel@suse.de>

#[cfg(any(test, fuzzing))]
use crate::address::Address;
use crate::address::{PhysAddr, VirtAddr};
use crate::utils::immut_after_init::ImmutAfterInitCell;

Expand All @@ -30,7 +28,7 @@ pub fn init_kernel_mapping_info(vstart: VirtAddr, vend: VirtAddr, pstart: PhysAd
.expect("Already initialized kernel mapping info");
}

#[cfg(not(any(test, fuzzing)))]
#[cfg(target_os = "none")]
pub fn virt_to_phys(vaddr: VirtAddr) -> PhysAddr {
if vaddr < KERNEL_MAPPING.virt_start || vaddr >= KERNEL_MAPPING.virt_end {
panic!("Invalid physical address {:#018x}", vaddr);
Expand All @@ -41,7 +39,7 @@ pub fn virt_to_phys(vaddr: VirtAddr) -> PhysAddr {
KERNEL_MAPPING.phys_start + offset
}

#[cfg(not(any(test, fuzzing)))]
#[cfg(target_os = "none")]
pub fn phys_to_virt(paddr: PhysAddr) -> VirtAddr {
let size: usize = KERNEL_MAPPING.virt_end - KERNEL_MAPPING.virt_start;
if paddr < KERNEL_MAPPING.phys_start || paddr >= KERNEL_MAPPING.phys_start + size {
Expand All @@ -53,13 +51,15 @@ pub fn phys_to_virt(paddr: PhysAddr) -> VirtAddr {
KERNEL_MAPPING.virt_start + offset
}

#[cfg(any(test, fuzzing))]
#[cfg(not(target_os = "none"))]
pub fn virt_to_phys(vaddr: VirtAddr) -> PhysAddr {
use crate::address::Address;
PhysAddr::from(vaddr.bits())
}

#[cfg(any(test, fuzzing))]
#[cfg(not(target_os = "none"))]
pub fn phys_to_virt(paddr: PhysAddr) -> VirtAddr {
use crate::address::Address;
VirtAddr::from(paddr.bits())
}

Expand Down
9 changes: 9 additions & 0 deletions src/mm/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1332,12 +1332,14 @@ impl Drop for TestRootMem<'_> {
}

#[test]
#[cfg_attr(test_in_svsm, ignore = "FIXME")]
fn test_root_mem_setup() {
let test_mem_lock = TestRootMem::setup(DEFAULT_TEST_MEMORY_SIZE);
drop(test_mem_lock);
}

#[test]
#[cfg_attr(test_in_svsm, ignore = "FIXME")]
// Allocate one page and free it again, verify that memory_info() reflects it.
fn test_page_alloc_one() {
let _test_mem = TestRootMem::setup(DEFAULT_TEST_MEMORY_SIZE);
Expand All @@ -1352,6 +1354,7 @@ fn test_page_alloc_one() {
}

#[test]
#[cfg_attr(test_in_svsm, ignore = "FIXME")]
// Allocate and free all available compound pages, verify that memory_info()
// reflects it.
fn test_page_alloc_all_compound() {
Expand Down Expand Up @@ -1384,6 +1387,7 @@ fn test_page_alloc_all_compound() {
}

#[test]
#[cfg_attr(test_in_svsm, ignore = "FIXME")]
// Allocate and free all available 4k pages, verify that memory_info()
// reflects it.
fn test_page_alloc_all_single() {
Expand Down Expand Up @@ -1416,6 +1420,7 @@ fn test_page_alloc_all_single() {
}

#[test]
#[cfg_attr(test_in_svsm, ignore = "FIXME")]
// Allocate and free all available compound pages, verify that any subsequent
// allocation fails.
fn test_page_alloc_oom() {
Expand Down Expand Up @@ -1453,6 +1458,7 @@ fn test_page_alloc_oom() {
}

#[test]
#[cfg_attr(test_in_svsm, ignore = "FIXME")]
fn test_page_file() {
let _mem_lock = TestRootMem::setup(DEFAULT_TEST_MEMORY_SIZE);
let mut root_mem = ROOT_MEM.lock();
Expand Down Expand Up @@ -1486,6 +1492,7 @@ fn test_page_file() {
const TEST_SLAB_SIZES: [usize; 7] = [32, 64, 128, 256, 512, 1024, 2048];

#[test]
#[cfg_attr(test_in_svsm, ignore = "FIXME")]
// Allocate and free a couple of objects for each slab size.
fn test_slab_alloc_free_many() {
extern crate alloc;
Expand Down Expand Up @@ -1525,6 +1532,7 @@ fn test_slab_alloc_free_many() {
}

#[test]
#[cfg_attr(test_in_svsm, ignore = "FIXME")]
// Allocate enough objects so that the SlabPageSlab will need a SlabPage for
// itself twice.
fn test_slab_page_slab_for_self() {
Expand Down Expand Up @@ -1561,6 +1569,7 @@ fn test_slab_page_slab_for_self() {
}

#[test]
#[cfg_attr(test_in_svsm, ignore = "FIXME")]
// Allocate enough objects to hit an OOM situation and verify null gets
// returned at some point.
fn test_slab_oom() {
Expand Down
7 changes: 5 additions & 2 deletions src/svsm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
//
// Author: Joerg Roedel <jroedel@suse.de>

#![no_std]
#![no_main]
#![cfg_attr(not(test), no_std)]
#![cfg_attr(not(test), no_main)]

extern crate alloc;

Expand Down Expand Up @@ -479,6 +479,9 @@ pub extern "C" fn svsm_main() {
panic!("Failed to launch FW: {:#?}", e);
}

#[cfg(test)]
crate::test_main();

request_loop();

panic!("Road ends here!");
Expand Down
Loading

0 comments on commit 6138015

Please sign in to comment.