Skip to content
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
16 changes: 7 additions & 9 deletions .github/workflows/qemu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ env:

jobs:
check:
name: QEMU NOCC boot test
name: QEMU NOCC test-in-svsm
runs-on: ubuntu-latest
steps:

Expand Down Expand Up @@ -106,20 +106,18 @@ jobs:
## TODO: We can replace the SVSM build step and download the IGVM file as an artifact
# from the "Rust check" jobs instread to speed things up.

- name: Install Rust x86_64-unknown-none
run: |
rustup toolchain install \
--profile minimal
- name: Install latest nightly
run: rustup toolchain install nightly -t x86_64-unknown-none --profile minimal --force -c rustfmt

- name: Install TPM 2.0 Reference Implementation build dependencies
run: sudo apt install -y autoconf autoconf-archive pkg-config build-essential automake

- name: Build SVSM
run: cargo xbuild configs/qemu-target.json
- name: Build test
run: make bin/coconut-test-qemu.igvm

########################

- name: Run SVSM in QEMU
- name: Run test-in-svsm in QEMU
run: |
QEMU=./tools/bin/qemu-system-x86_64 scripts/test-qemu-nocc-boot.sh
QEMU=./tools/bin/qemu-system-x86_64 scripts/test-qemu-nocc-svsm.sh

4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ ifneq ($(FEATURES_TEST),)
SVSM_ARGS_TEST += --features ${FEATURES_TEST}
endif

TEST_ARGS ?=

CLIPPY_OPTIONS ?=
CLIPPY_ARGS ?= -D warnings

Expand Down Expand Up @@ -115,7 +117,7 @@ test:
test-igvm: bin/coconut-test-qemu.igvm bin/coconut-test-hyperv.igvm bin/coconut-test-vanadium.igvm

test-in-svsm: utils/cbit bin/coconut-test-qemu.igvm $(IGVMMEASUREBIN)
./scripts/test-in-svsm.sh
./scripts/test-in-svsm.sh $(TEST_ARGS)

test-in-hyperv: bin/coconut-test-hyperv.igvm

Expand Down
4 changes: 4 additions & 0 deletions kernel/src/cpu/vc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,10 @@ mod tests {
#[test]
#[cfg_attr(not(test_in_svsm), ignore = "Can only be run inside guest")]
fn test_has_memory_encryption_info_cpuid() {
if is_test_platform_type(SvsmPlatformType::Native) {
return;
}

const CPUID_EXTENDED_FUNCTION_INFO: u32 = 0x8000_0000;
const CPUID_MEMORY_ENCRYPTION_INFO: u32 = 0x8000_001F;
// SAFETY: CPUID does never affect safety.
Expand Down
2 changes: 2 additions & 0 deletions kernel/src/svsm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,8 @@ fn panic(info: &PanicInfo<'_>) -> ! {

loop {
debug_break();
#[cfg(all(test, test_in_svsm))]
crate::testing::qemu_write_exit(crate::testing::QEMUExitValue::Fail);
platform::halt();
}
}
25 changes: 17 additions & 8 deletions kernel/src/testing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@ use log::info;
use test::ShouldPanic;

use crate::{
cpu::percpu::current_ghcb,
locking::{LockGuard, SpinLock},
platform::SVSM_PLATFORM,
serial::SerialPort,
sev::ghcb::GHCBIOSize,
testutils::has_qemu_testdev,
};

Expand Down Expand Up @@ -90,15 +88,26 @@ pub fn svsm_test_runner(test_cases: &[&test::TestDescAndFn]) {
}

fn exit() -> ! {
if has_qemu_testdev() {
const QEMU_EXIT_PORT: u16 = 0xf4;
current_ghcb()
.ioio_out(QEMU_EXIT_PORT, GHCBIOSize::Size32, 0)
.unwrap();
}
qemu_write_exit(QEMUExitValue::Success);
// SAFETY: HLT instruction does not affect memory.
unsafe {
asm!("hlt");
}
unreachable!();
}

#[repr(u32)]
#[derive(Debug)]
pub enum QEMUExitValue {
Success = 0x10,
Fail = 0x11,
}

pub fn qemu_write_exit(value: QEMUExitValue) {
if has_qemu_testdev() {
const QEMU_EXIT_PORT: u16 = 0xf4;
SVSM_PLATFORM
.get_io_port()
.outl(QEMU_EXIT_PORT, value as u32);
}
}
31 changes: 30 additions & 1 deletion scripts/test-in-svsm.sh
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,38 @@ dd if=/dev/urandom of="$TEST_DIR/svsm_state.raw" bs=512 count=1024
test_io $TEST_DIR/pipe.in $TEST_DIR/pipe.out &
TEST_IO_PID=$!

LAUNCH_GUEST_ARGS=""

while [[ $# -gt 0 ]]; do
case $1 in
--nocc)
LAUNCH_GUEST_ARGS+="--nocc "
shift
;;
*)
echo "Invalid parameter $1"
exit 1
;;
esac
done


$SCRIPT_DIR/launch_guest.sh --igvm $SCRIPT_DIR/../bin/coconut-test-qemu.igvm \
--state "$TEST_DIR/svsm_state.raw" \
--unit-tests $TEST_DIR/pipe || true
--unit-tests $TEST_DIR/pipe \
$LAUNCH_GUEST_ARGS || svsm_exit_code=$?

# SVSM writes 0x10 to the QEMU exit port when all tests passed.
# This results in QEMU returning 0x21 ((0x10 << 1) | 1)
if [[ $svsm_exit_code -eq 0x21 ]]; then
echo "All tests passed"
exit_value=0
else
echo "Test Failed"
exit_value=1
fi

kill $TEST_IO_PID 2> /dev/null || true
rm -rf $TEST_DIR

exit $exit_value
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)

# When we see this string on the serial output, consider
# SVSM booted and the test passed.
SUCCESS="Terminating task init"
SUCCESS="All tests passed"

# Fail the test after this timeout
TIMEOUT=4s
TIMEOUT=180s

# Clone STDOUT for live log reporting
exec 3>&1

echo "================================================================================"
timeout $TIMEOUT \
grep -q -m 1 "$SUCCESS" \
<("$SCRIPT_DIR/launch_guest.sh" --nocc | tee /proc/self/fd/3)
<("$SCRIPT_DIR/test-in-svsm.sh" --nocc | tee /proc/self/fd/3)
RES=$?
echo "================================================================================"

Expand Down