diff --git a/guest-test/guest.test_executor.sh b/guest-test/guest.test_executor.sh index cfcbfa6d..39be2e14 100755 --- a/guest-test/guest.test_executor.sh +++ b/guest-test/guest.test_executor.sh @@ -59,13 +59,13 @@ EOF return 1 fi EOF -ERR_NUM=$? -if [ $ERR_NUM -eq 0 ]; then - test_print_trc "Guest VM test source code and binary prepare complete" - return 0 -else - return 1 -fi + ERR_NUM=$? + if [ $ERR_NUM -eq 0 ]; then + test_print_trc "Guest VM test source code and binary prepare complete" + return 0 + else + return 1 + fi } # function based on sshpass to execute $1 test_script.sh and potential $2 script params in Guest VM @@ -77,12 +77,12 @@ guest_test_entry() { test_print_trc "guest_test_entry args 2: $2" ./$1 $2 EOF -ERR_NUM=$? -if [ $ERR_NUM -eq 0 ] || [ $ERR_NUM -eq 255 ]; then - return 0 -else - return 1 -fi + ERR_NUM=$? + if [ $ERR_NUM -eq 0 ] || [ $ERR_NUM -eq 255 ]; then + return 0 + else + return 1 + fi } # function based on sshpass to close VM @@ -92,7 +92,13 @@ guest_test_close() { test_print_trc "guest test complete, close VM now" systemctl reboot --reboot-argument=now EOF - test_print_trc "Guest VM closed properly after test" + ERR_NUM=$? + if [ $ERR_NUM -eq 0 ]; then + test_print_trc "Guest VM closed properly after test" + return 0 + else + return 1 + fi } ###################### Do Works ###################### @@ -109,4 +115,4 @@ if [ "${BASH_SOURCE[0]}" -ef "$0" ]; then # select specific "$FEATURE.test_executor.sh" by $FEATURE "$FEATURE"/"$FEATURE".test_executor.sh || \ { die "Failed on $TESTCASE of $FEATURE"; return 1; } -fi \ No newline at end of file +fi diff --git a/guest-test/guest.test_launcher.sh b/guest-test/guest.test_launcher.sh index 5ac148b6..81b7eec6 100755 --- a/guest-test/guest.test_launcher.sh +++ b/guest-test/guest.test_launcher.sh @@ -25,7 +25,7 @@ echo "$SCRIPT_DIR" GCOV="off" # timeout control in case of TD VM booting hang SECONDS=0 -TIMEOUT=300 +TIMEOUT=900 # EXEC_FLAG=0 shows test_executor being called EXEC_FLAG=1 @@ -249,8 +249,13 @@ while read -r line; do elif [[ $SECONDS -ge $TIMEOUT ]]; then # break while read loop in case of TD VM boot timeout (no $BOOT_PATTERN found) break fi -done < <(if [ "$GCOV" == "off" ]; then timeout "$TIMEOUT" ./guest.qemu_runner.sh; \ - else test_print_trc "${VM_TYPE}vm_$PORT keep alive for gcov data collection" && ./guest.qemu_runner.sh; fi) +done < <( + if [ "$GCOV" == "off" ]; then + timeout "$TIMEOUT" ./guest.qemu_runner.sh + else + test_print_trc "${VM_TYPE}vm_$PORT keep alive for gcov data collection" && ./guest.qemu_runner.sh + fi +) ## PART 3: err_handlers error management # unexpected error/bug/warning/call trace handling diff --git a/guest-test/tdx/tdx.test_executor.sh b/guest-test/tdx/tdx.test_executor.sh index b1b1cb22..b36ef4b7 100755 --- a/guest-test/tdx/tdx.test_executor.sh +++ b/guest-test/tdx/tdx.test_executor.sh @@ -29,7 +29,7 @@ guest_attest_test() { guest_test_entry tdx_attest_check.sh "-t $selftest_item" || \ { die "Failed on $TESTCASE tdx_attest_check.sh -t $selftest_item"; return 1; } if [[ $GCOV == "off" ]]; then - guest_test_close + guest_test_close || { die "Failed on close guest VM"; return 1; } fi } @@ -39,7 +39,7 @@ guest_tsm_attest() { guest_test_entry tdx_attest_check.sh "-t $test_item" || \ { die "Failed on $TESTCASE tdx_attest_check.sh -t $test_item"; return 1; } if [[ $GCOV == "off" ]]; then - guest_test_close + guest_test_close || { die "Failed on close guest VM"; return 1; } fi } @@ -70,16 +70,16 @@ case "$TESTCASE" in guest_test_entry tdx_guest_boot_check.sh "-v $VCPU -s $SOCKETS -m $MEM" || \ die "Failed on TD_BOOT test tdx_guest_boot_check.sh -v $VCPU -s $SOCKETS -m $MEM" if [[ $GCOV == "off" ]]; then - guest_test_close + guest_test_close || { die "Failed on close guest VM"; return 1; } fi ;; GUEST_TESTCASE_EXAMPLE) guest_test_prepare guest_test.sh guest_test_source_code test_source_code_dir_example test_binary_example guest_test_entry guest_test.sh "-t $TESTCASE" || \ - die "Failed on $TESTCASE guest_test.sh -t $TESTCASE" + { die "Failed on $TESTCASE guest_test.sh -t $TESTCASE"; return 1; } if [[ $GCOV == "off" ]]; then - guest_test_close + guest_test_close || { die "Failed on close guest VM"; return 1; } fi ;; TD_ATTEST_VERIFY_REPORT) @@ -103,7 +103,7 @@ case "$TESTCASE" in guest_test_entry tdx_speed_test.sh || \ die "Failed on TD_NET_SPEED tdx_speed_test.sh" if [[ $GCOV == "off" ]]; then - guest_test_close + guest_test_close || { die "Failed on close guest VM"; return 1; } fi ;; TD_TSM_ATTEST_QUOTE_PRECHECK) @@ -125,7 +125,7 @@ case "$TESTCASE" in guest_test_entry tdx_mem_test.sh "-t EBIZZY_FUNC" || \ { die "Failed on $TESTCASE tdx_mem_test.sh -t EBIZZY_FUNC"; return 1; } if [[ $GCOV == "off" ]]; then - guest_test_close + guest_test_close || { die "Failed on close guest VM"; return 1; } fi ;; TD_MEM_ACPT_T_1C_8G_1W) @@ -133,7 +133,7 @@ case "$TESTCASE" in guest_test_entry tdx_mem_test.sh "-t MEM_ACPT_T_1C_8G_1W" || \ { die "Failed on $TESTCASE tdx_mem_test.sh -t MEM_ACPT_T_1C_8G_1W"; return 1; } if [[ $GCOV == "off" ]]; then - guest_test_close + guest_test_close || { die "Failed on close guest VM"; return 1; } fi ;; TD_MEM_ACPT_T_1C_8G_32W) @@ -141,7 +141,7 @@ case "$TESTCASE" in guest_test_entry tdx_mem_test.sh "-t MEM_ACPT_T_1C_8G_32W" || \ { die "Failed on $TESTCASE tdx_mem_test.sh -t MEM_ACPT_T_1C_8G_32W"; return 1; } if [[ $GCOV == "off" ]]; then - guest_test_close + guest_test_close || { die "Failed on close guest VM"; return 1; } fi ;; TD_MEM_ACPT_T_1C_32G_1W) @@ -149,7 +149,7 @@ case "$TESTCASE" in guest_test_entry tdx_mem_test.sh "-t MEM_ACPT_T_1C_32G_1W" || \ { die "Failed on $TESTCASE tdx_mem_test.sh -t MEM_ACPT_T_1C_32G_1W"; return 1; } if [[ $GCOV == "off" ]]; then - guest_test_close + guest_test_close || { die "Failed on close guest VM"; return 1; } fi ;; TD_MEM_ACPT_T_1C_32G_32W) @@ -157,7 +157,7 @@ case "$TESTCASE" in guest_test_entry tdx_mem_test.sh "-t MEM_ACPT_T_1C_32G_32W" || \ { die "Failed on $TESTCASE tdx_mem_test.sh -t MEM_ACPT_T_1C_32G_32W"; return 1; } if [[ $GCOV == "off" ]]; then - guest_test_close + guest_test_close || { die "Failed on close guest VM"; return 1; } fi ;; TD_MEM_ACPT_T_1C_96G_1W) @@ -165,7 +165,7 @@ case "$TESTCASE" in guest_test_entry tdx_mem_test.sh "-t MEM_ACPT_T_1C_96G_1W" || \ { die "Failed on $TESTCASE tdx_mem_test.sh -t MEM_ACPT_T_1C_96G_1W"; return 1; } if [[ $GCOV == "off" ]]; then - guest_test_close + guest_test_close || { die "Failed on close guest VM"; return 1; } fi ;; TD_MEM_ACPT_T_1C_96G_32W) @@ -173,7 +173,7 @@ case "$TESTCASE" in guest_test_entry tdx_mem_test.sh "-t MEM_ACPT_T_1C_96G_32W" || \ { die "Failed on $TESTCASE tdx_mem_test.sh -t MEM_ACPT_T_1C_96G_32W"; return 1; } if [[ $GCOV == "off" ]]; then - guest_test_close + guest_test_close || { die "Failed on close guest VM"; return 1; } fi ;; TD_MEM_ACPT_T_32C_8G_32W) @@ -181,7 +181,7 @@ case "$TESTCASE" in guest_test_entry tdx_mem_test.sh "-t MEM_ACPT_T_32C_8G_32W" || \ { die "Failed on $TESTCASE tdx_mem_test.sh -t MEM_ACPT_T_32C_8G_32W"; return 1; } if [[ $GCOV == "off" ]]; then - guest_test_close + guest_test_close || { die "Failed on close guest VM"; return 1; } fi ;; TD_MEM_ACPT_T_32C_8G_256W) @@ -189,7 +189,7 @@ case "$TESTCASE" in guest_test_entry tdx_mem_test.sh "-t MEM_ACPT_T_32C_8G_256W" || \ { die "Failed on $TESTCASE tdx_mem_test.sh -t MEM_ACPT_T_32C_8G_256W"; return 1; } if [[ $GCOV == "off" ]]; then - guest_test_close + guest_test_close || { die "Failed on close guest VM"; return 1; } fi ;; TD_MEM_ACPT_T_32C_32G_32W) @@ -197,7 +197,7 @@ case "$TESTCASE" in guest_test_entry tdx_mem_test.sh "-t MEM_ACPT_T_32C_32G_32W" || \ { die "Failed on $TESTCASE tdx_mem_test.sh -t MEM_ACPT_T_32C_32G_32W"; return 1; } if [[ $GCOV == "off" ]]; then - guest_test_close + guest_test_close || { die "Failed on close guest VM"; return 1; } fi ;; TD_MEM_ACPT_T_32C_32G_256W) @@ -205,7 +205,7 @@ case "$TESTCASE" in guest_test_entry tdx_mem_test.sh "-t MEM_ACPT_T_32C_32G_256W" || \ { die "Failed on $TESTCASE tdx_mem_test.sh -t MEM_ACPT_T_32C_32G_256W"; return 1; } if [[ $GCOV == "off" ]]; then - guest_test_close + guest_test_close || { die "Failed on close guest VM"; return 1; } fi ;; TD_MEM_ACPT_T_32C_96G_32W) @@ -213,7 +213,7 @@ case "$TESTCASE" in guest_test_entry tdx_mem_test.sh "-t MEM_ACPT_T_32C_96G_32W" || \ { die "Failed on $TESTCASE tdx_mem_test.sh -t MEM_ACPT_T_32C_96G_32W"; return 1; } if [[ $GCOV == "off" ]]; then - guest_test_close + guest_test_close || { die "Failed on close guest VM"; return 1; } fi ;; TD_MEM_ACPT_T_32C_96G_256W) @@ -221,7 +221,41 @@ case "$TESTCASE" in guest_test_entry tdx_mem_test.sh "-t MEM_ACPT_T_32C_96G_256W" || \ { die "Failed on $TESTCASE tdx_mem_test.sh -t MEM_ACPT_T_32C_96G_256W"; return 1; } if [[ $GCOV == "off" ]]; then - guest_test_close + guest_test_close || { die "Failed on close guest VM"; return 1; } + fi + ;; + TD_MEM_ACPT_FUNC) + guest_test_prepare tdx_mem_test.sh + guest_test_entry tdx_mem_test.sh "-t MEM_ACPT_FUNC" || \ + { die "Failed on $TESTCASE tdx_mem_test.sh -t MEM_ACPT_FUNC"; return 1; } + if [[ $GCOV == "off" ]]; then + guest_test_close || { die "Failed on close guest VM"; return 1; } + fi + ;; + TD_MEM_ACPT_CAL) + guest_test_prepare tdx_mem_test.sh + guest_test_entry tdx_mem_test.sh "-t MEM_ACPT_CAL" || \ + { die "Failed on $TESTCASE tdx_mem_test.sh -t MEM_ACPT_CAL"; return 1; } + if [[ $GCOV == "off" ]]; then + guest_test_close || { die "Failed on close guest VM"; return 1; } + fi + ;; + TD_MEM_ACPT_NEG) + guest_test_prepare tdx_mem_test.sh + guest_test_entry tdx_mem_test.sh "-t MEM_ACPT_NEG" || \ + { die "Failed on $TESTCASE tdx_mem_test.sh -t MEM_ACPT_NEG"; return 1; } + if [[ $GCOV == "off" ]]; then + guest_test_close || { die "Failed on close guest VM"; return 1; } + fi + ;; + TD_VE_HALT) + guest_test_prepare tdx_test_module.sh + guest_test_source_code tdx_halt_test_module halt_test || \ + { die "Failed to prepare guest test kernel module for $TESTCASE"; return 1; } + guest_test_entry tdx_test_module.sh "halt_test" || \ + { die "Failed on $TESTCASE tdx_test_module.sh halt_test"; return 1; } + if [[ $GCOV == "off" ]]; then + guest_test_close || { die "Failed on close guest VM"; return 1; } fi ;; :) diff --git a/guest-test/tdx/tdx_halt_test_module/.gitignore b/guest-test/tdx/tdx_halt_test_module/.gitignore new file mode 100644 index 00000000..b0a810a9 --- /dev/null +++ b/guest-test/tdx/tdx_halt_test_module/.gitignore @@ -0,0 +1 @@ +halt_test.ko \ No newline at end of file diff --git a/guest-test/tdx/tdx_halt_test_module/Makefile b/guest-test/tdx/tdx_halt_test_module/Makefile new file mode 100644 index 00000000..97e0e4f1 --- /dev/null +++ b/guest-test/tdx/tdx_halt_test_module/Makefile @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-only + +MODULES = halt_test.ko + +obj-m += halt_test.o + +KDIR ?= /lib/modules/$(shell uname -r)/build + +all: + make -C $(KDIR) M=$(PWD) modules +clean: + make -C $(KDIR) M=$(PWD) clean \ No newline at end of file diff --git a/guest-test/tdx/tdx_halt_test_module/halt_test.c b/guest-test/tdx/tdx_halt_test_module/halt_test.c new file mode 100644 index 00000000..13c2b943 --- /dev/null +++ b/guest-test/tdx/tdx_halt_test_module/halt_test.c @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include +#include +#include + +static int __init test_tdx_hlt_init(void) +{ + pr_info("[TD guest test] Start to trigger hlt instr.\n"); + asm("cli"); + asm("hlt"); + return 0; +} + +static void __exit test_tdx_hlt_exit(void) +{ + pr_info("[TD guest test] Complete of hlt instr. test, test module exit\n"); +} + +module_init(test_tdx_hlt_init); +module_exit(test_tdx_hlt_exit); +MODULE_INFO(intree, "Y"); +MODULE_LICENSE("GPL"); diff --git a/guest-test/tdx/tdx_mem_test.sh b/guest-test/tdx/tdx_mem_test.sh index 3bdb3943..4b28d5cb 100755 --- a/guest-test/tdx/tdx_mem_test.sh +++ b/guest-test/tdx/tdx_mem_test.sh @@ -45,11 +45,11 @@ ebizzy_func() { # function based on stress-ng calculate total remained mem accepted time mem_accepted_time() { -# common expected time consumed in seconds -expected_time=$1 -# stress-ng mem stress process number -workers=$2 -# prepare for prerequisites + # common expected time consumed in seconds + expected_time=$1 + # stress-ng mem stress process number + workers=$2 + # prepare for prerequisites if [ ! "$(which stress-ng)" ]; then dnf install -y stress-ng > /dev/null apt install -y stress-ng > /dev/null @@ -57,28 +57,76 @@ workers=$2 test_print_trc "stress-ng prerequisites is ready for use" test_print_trc "unaccepted memory drained time calculation is starting now..." fi -# calculate memory accepted fully completed time -SECONDS=0 -stress-ng --vm "$workers" --vm-bytes 100% & -while (true); do - if [[ $(grep "nr_unaccepted" /proc/vmstat | awk '{print $2}') -eq 0 ]]; then - actual_time=$SECONDS; - pkill stress-ng; - break; + # calculate memory accepted fully completed time + SECONDS=0 + stress-ng --vm "$workers" --vm-bytes 100% & + while (true); do + if [[ $(grep "nr_unaccepted" /proc/vmstat | awk '{print $2}') -eq 0 ]]; then + actual_time=$SECONDS; + pkill stress-ng; + break; + fi + done + # check if memory accept time far exceed expected (passed in value) + compare_result=$(echo "scale=2; ($actual_time/$expected_time)" | bc) + baseline_result=1.1 + result=$(awk -v n1="$compare_result" -v n2="$baseline_result" 'BEGIN {if (n1>n2) print 1; else print 0}') + if [ "$result" -eq 0 ]; then + test_print_trc "Memory accepted full time consumed: $actual_time" + return 0 + else + die "Memory accepted full time consumed: $actual_time seconds" + die "It's over expectation $expected_time seconds 10% more!!!" + return 1 + fi +} + +# function based on stress-ng do basic mem lazy accept function check +mem_accept_func() { + # prepare for prerequisites + if [ ! "$(which stress-ng)" ]; then + dnf install -y stress-ng > /dev/null + apt install -y stress-ng > /dev/null + else + test_print_trc "stress-ng prerequisites is ready for use" + test_print_trc "unaccepted memory drained time calculation is starting now..." + fi + bootup_vmstat=$(grep "nr_unaccepted" /proc/vmstat | cut -d' ' -f2) + stress-ng --vm 1 --vm-bytes 10% --timeout 3s + stress_vmstat=$(grep "nr_unaccepted" /proc/vmstat | cut -d' ' -f2) + if [[ "$bootup_vmstat" -gt "$stress_vmstat" ]]; then + test_print_trc "TD VM unaccepted memory func test PASS" + else + die "TD VM unaccepted memory func test FAIL" + return 1 + fi +} + +# function mem lazy accept info calculation +mem_accept_cal() { + test_print_trc "Start TD VM unaccepted memory info calculation check" + vmstat=$(grep "nr_unaccepted" /proc/vmstat | cut -d' ' -f2) + meminfo=$(awk '/Unaccepted/{printf "%d\n", $2;}' n2) print 1; else print 0}') -if [ "$result" -eq 0 ]; then - test_print_trc "Memory accepted full time consumed: $actual_time" - return 0 -else - die "Memory accepted full time consumed: $actual_time seconds" - die "It's over expectation $expected_time seconds 10% more!!!" - return 1 -fi } ###################### Do Works ###################### @@ -146,6 +194,15 @@ case "$MEM_CASE" in # 32VCPU + 96G MEM + 256 mem stress processes mem_accepted_time 92 256 ;; + MEM_ACPT_FUNC) + mem_accept_func + ;; + MEM_ACPT_CAL) + mem_accept_cal + ;; + MEM_ACPT_NEG) + mem_accept_neg + ;; :) test_print_err "Must specify the memory case option by [-t]" exit 1 diff --git a/guest-test/tdx/tdx_test_module.sh b/guest-test/tdx/tdx_test_module.sh new file mode 100755 index 00000000..67224d92 --- /dev/null +++ b/guest-test/tdx/tdx_test_module.sh @@ -0,0 +1,38 @@ +#!/usr/bin/bash +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (c) 2023 Intel Corporation + +# Author: Hongyu Ning +# +# History: 13, Dec., 2023 - Hongyu Ning - creation + + +# @desc This script do test by kernel test module in TDX Guest VM + +###################### Variables ###################### +SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )" +echo "$SCRIPT_DIR" +source common.sh +test_module=$1 + +###################### Functions ###################### +module_check() { + lsmod | grep "$test_module" || \ + { die "test module $test_module not found in lsmod"; return 1; } + test_print_trc "test module loaded and test should be completed now" +} + +###################### Do Works ###################### +if [[ -f "$test_module".ko ]]; then + test_print_trc "Kernel test module: $test_module.ko is ready for test" + insmod "$test_module".ko || \ + { die "Fail to insmod test module $test_module.ko"; exit 1; } + test_print_trc "$test_module.ko inserted and hlt instruction triggered" + module_check + sleep 3 + rmmod "$test_module" || \ + { die "Fail to rmmod test module $test_module.ko"; exit 1; } +else + die "Kernel test module $test_module.ko not found" + exit 1 +fi \ No newline at end of file diff --git a/guest-test/tdx/tests b/guest-test/tdx/tests index 874c69ae..23cf850c 100644 --- a/guest-test/tdx/tests +++ b/guest-test/tdx/tests @@ -31,4 +31,9 @@ guest.test_launcher.sh -v 32 -s 1 -m 8 -d on -t tdx -f tdx -x TD_MEM_ACPT_T_32C_ guest.test_launcher.sh -v 32 -s 1 -m 32 -d on -t tdx -f tdx -x TD_MEM_ACPT_T_32C_32G_32W -c "accept_memory=lazy" -p off guest.test_launcher.sh -v 32 -s 1 -m 32 -d on -t tdx -f tdx -x TD_MEM_ACPT_T_32C_32G_256W -c "accept_memory=lazy" -p off guest.test_launcher.sh -v 32 -s 1 -m 96 -d on -t tdx -f tdx -x TD_MEM_ACPT_T_32C_96G_32W -c "accept_memory=lazy" -p off -guest.test_launcher.sh -v 32 -s 1 -m 96 -d on -t tdx -f tdx -x TD_MEM_ACPT_T_32C_96G_256W -c "accept_memory=lazy" -p off \ No newline at end of file +guest.test_launcher.sh -v 32 -s 1 -m 96 -d on -t tdx -f tdx -x TD_MEM_ACPT_T_32C_96G_256W -c "accept_memory=lazy" -p off +guest.test_launcher.sh -v 1 -s 1 -m 16 -d on -t tdx -f tdx -x TD_MEM_ACPT_FUNC -c "accept_memory=lazy" -p off +guest.test_launcher.sh -v 1 -s 1 -m 16 -d on -t tdx -f tdx -x TD_MEM_ACPT_CAL -c "accept_memory=lazy" -p off +guest.test_launcher.sh -v 1 -s 1 -m 16 -d on -t tdx -f tdx -x TD_MEM_ACPT_NEG -c "accept_memory=eager" -p off +# case implemented by tdx_test_module.sh +guest.test_launcher.sh -v 1 -s 1 -m 1 -d on -t tdx -f tdx -x TD_VE_HALT -c "accept_memory=lazy" -p off \ No newline at end of file