@@ -731,8 +731,8 @@ static int test_run(struct vmx_test *test)
init_vmcs(&(test->vmcs));
/* Directly call test->init is ok here, init_vmcs has done
vmcs init, vmclear and vmptrld*/
- if (test->init)
- test->init(test->vmcs);
+ if (test->init && test->init(test->vmcs) != VMX_TEST_START)
+ return 0;
test->exits = 0;
current = test;
regs = test->guest_regs;
@@ -32,7 +32,7 @@ struct regs {
struct vmx_test {
const char *name;
- void (*init)(struct vmcs *vmcs);
+ int (*init)(struct vmcs *vmcs);
void (*guest_main)();
int (*exit_handler)();
void (*syscall_handler)(u64 syscall_no);
@@ -434,6 +434,7 @@ enum Ctrl1 {
#define VMX_IO_PORT_MASK 0xFFFF0000
#define VMX_IO_PORT_SHIFT 16
+#define VMX_TEST_START 0
#define VMX_TEST_VMEXIT 1
#define VMX_TEST_EXIT 2
#define VMX_TEST_RESUME 3
@@ -16,7 +16,6 @@ volatile u32 stage;
void *io_bitmap_a, *io_bitmap_b;
u16 ioport;
-bool init_fail;
unsigned long *pml4;
u64 eptp;
void *data_page1, *data_page2;
@@ -119,28 +118,26 @@ u32 preempt_scale;
volatile unsigned long long tsc_val;
volatile u32 preempt_val;
-void preemption_timer_init()
+int preemption_timer_init()
{
- u32 ctrl_pin;
-
- ctrl_pin = vmcs_read(PIN_CONTROLS) | PIN_PREEMPT;
- ctrl_pin &= ctrl_pin_rev.clr;
- vmcs_write(PIN_CONTROLS, ctrl_pin);
+ if (!(ctrl_pin_rev.clr & PIN_PREEMPT)) {
+ printf("\tPreemption timer is not supported\n");
+ return VMX_TEST_EXIT;
+ }
+ vmcs_write(PIN_CONTROLS, vmcs_read(PIN_CONTROLS) | PIN_PREEMPT);
preempt_val = 10000000;
vmcs_write(PREEMPT_TIMER_VALUE, preempt_val);
preempt_scale = rdmsr(MSR_IA32_VMX_MISC) & 0x1F;
if (!(ctrl_exit_rev.clr & EXI_SAVE_PREEMPT))
printf("\tSave preemption value is not supported\n");
+
+ return VMX_TEST_START;
}
void preemption_timer_main()
{
tsc_val = rdtsc();
- if (!(ctrl_pin_rev.clr & PIN_PREEMPT)) {
- printf("\tPreemption timer is not supported\n");
- return;
- }
if (ctrl_exit_rev.clr & EXI_SAVE_PREEMPT) {
set_stage(0);
vmcall();
@@ -223,7 +220,7 @@ void msr_bmp_init()
vmcs_write(MSR_BITMAP, (u64)msr_bitmap);
}
-static void test_ctrl_pat_init()
+static int test_ctrl_pat_init()
{
u64 ctrl_ent;
u64 ctrl_exi;
@@ -236,6 +233,7 @@ static void test_ctrl_pat_init()
ia32_pat = rdmsr(MSR_IA32_CR_PAT);
vmcs_write(GUEST_PAT, 0x0);
vmcs_write(HOST_PAT, ia32_pat);
+ return VMX_TEST_START;
}
static void test_ctrl_pat_main()
@@ -301,7 +299,7 @@ static int test_ctrl_pat_exit_handler()
return VMX_TEST_VMEXIT;
}
-static void test_ctrl_efer_init()
+static int test_ctrl_efer_init()
{
u64 ctrl_ent;
u64 ctrl_exi;
@@ -314,6 +312,7 @@ static void test_ctrl_efer_init()
ia32_efer = rdmsr(MSR_EFER);
vmcs_write(GUEST_EFER, ia32_efer ^ EFER_NX);
vmcs_write(HOST_EFER, ia32_efer ^ EFER_NX);
+ return VMX_TEST_START;
}
static void test_ctrl_efer_main()
@@ -589,7 +588,7 @@ static int cr_shadowing_exit_handler()
return VMX_TEST_VMEXIT;
}
-static void iobmp_init()
+static int iobmp_init()
{
u32 ctrl_cpu0;
@@ -603,6 +602,7 @@ static void iobmp_init()
vmcs_write(CPU_EXEC_CTRL0, ctrl_cpu0);
vmcs_write(IO_BITMAP_A, (u64)io_bitmap_a);
vmcs_write(IO_BITMAP_B, (u64)io_bitmap_b);
+ return VMX_TEST_START;
}
static void iobmp_main()
@@ -814,7 +814,7 @@ static struct insn_table insn_table[] = {
{NULL},
};
-static void insn_intercept_init()
+static int insn_intercept_init()
{
u32 ctrl_cpu[2];
@@ -827,6 +827,7 @@ static void insn_intercept_init()
ctrl_cpu[1] |= CPU_WBINVD | CPU_RDRAND;
ctrl_cpu[1] &= ctrl_cpu_rev[1].clr;
vmcs_write(CPU_EXEC_CTRL1, ctrl_cpu[1]);
+ return VMX_TEST_START;
}
static void insn_intercept_main()
@@ -926,12 +927,17 @@ static int setup_ept()
return 0;
}
-static void ept_init()
+static int ept_init()
{
unsigned long base_addr1, base_addr2;
u32 ctrl_cpu[2];
- init_fail = false;
+ if (!(ctrl_cpu_rev[0].clr & CPU_SECONDARY) ||
+ !(ctrl_cpu_rev[1].clr & CPU_EPT)) {
+ printf("\tEPT is not supported");
+ return VMX_TEST_EXIT;
+ }
+
ctrl_cpu[0] = vmcs_read(CPU_EXEC_CTRL0);
ctrl_cpu[1] = vmcs_read(CPU_EXEC_CTRL1);
ctrl_cpu[0] = (ctrl_cpu[0] | CPU_SECONDARY)
@@ -941,7 +947,7 @@ static void ept_init()
vmcs_write(CPU_EXEC_CTRL0, ctrl_cpu[0]);
vmcs_write(CPU_EXEC_CTRL1, ctrl_cpu[1]);
if (setup_ept())
- init_fail = true;
+ return VMX_TEST_EXIT;
data_page1 = alloc_page();
data_page2 = alloc_page();
memset(data_page1, 0x0, PAGE_SIZE);
@@ -954,20 +960,14 @@ static void ept_init()
EPT_WA | EPT_RA | EPT_EA) ||
setup_ept_range(pml4, base_addr2, base_addr2 + PAGE_SIZE_2M, 0, 0,
EPT_WA | EPT_RA | EPT_EA))
- init_fail = true;
+ return VMX_TEST_EXIT;
install_ept(pml4, (unsigned long)data_page1, (unsigned long)data_page2,
EPT_RA | EPT_WA | EPT_EA);
+ return VMX_TEST_START;
}
static void ept_main()
{
- if (init_fail)
- return;
- if (!(ctrl_cpu_rev[0].clr & CPU_SECONDARY) ||
- !(ctrl_cpu_rev[1].clr & CPU_EPT)) {
- printf("\tEPT is not supported");
- return;
- }
set_stage(0);
if (*((u32 *)data_page2) != MAGIC_VAL_1 ||
*((u32 *)data_page1) != MAGIC_VAL_1)
If some feature is not existing and, thus, a test case is not able to run, already report this back from the init handler. Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> --- x86/vmx.c | 4 ++-- x86/vmx.h | 3 ++- x86/vmx_tests.c | 52 ++++++++++++++++++++++++++-------------------------- 3 files changed, 30 insertions(+), 29 deletions(-)