vmx_close_while_nested_test.c (1881B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * vmx_close_while_nested 4 * 5 * Copyright (C) 2019, Red Hat, Inc. 6 * 7 * Verify that nothing bad happens if a KVM user exits with open 8 * file descriptors while executing a nested guest. 9 */ 10 11#include "test_util.h" 12#include "kvm_util.h" 13#include "processor.h" 14#include "vmx.h" 15 16#include <string.h> 17#include <sys/ioctl.h> 18 19#include "kselftest.h" 20 21#define VCPU_ID 5 22 23enum { 24 PORT_L0_EXIT = 0x2000, 25}; 26 27/* The virtual machine object. */ 28static struct kvm_vm *vm; 29 30static void l2_guest_code(void) 31{ 32 /* Exit to L0 */ 33 asm volatile("inb %%dx, %%al" 34 : : [port] "d" (PORT_L0_EXIT) : "rax"); 35} 36 37static void l1_guest_code(struct vmx_pages *vmx_pages) 38{ 39#define L2_GUEST_STACK_SIZE 64 40 unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; 41 42 GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); 43 GUEST_ASSERT(load_vmcs(vmx_pages)); 44 45 /* Prepare the VMCS for L2 execution. */ 46 prepare_vmcs(vmx_pages, l2_guest_code, 47 &l2_guest_stack[L2_GUEST_STACK_SIZE]); 48 49 GUEST_ASSERT(!vmlaunch()); 50 GUEST_ASSERT(0); 51} 52 53int main(int argc, char *argv[]) 54{ 55 vm_vaddr_t vmx_pages_gva; 56 57 nested_vmx_check_supported(); 58 59 vm = vm_create_default(VCPU_ID, 0, (void *) l1_guest_code); 60 61 /* Allocate VMX pages and shared descriptors (vmx_pages). */ 62 vcpu_alloc_vmx(vm, &vmx_pages_gva); 63 vcpu_args_set(vm, VCPU_ID, 1, vmx_pages_gva); 64 65 for (;;) { 66 volatile struct kvm_run *run = vcpu_state(vm, VCPU_ID); 67 struct ucall uc; 68 69 vcpu_run(vm, VCPU_ID); 70 TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, 71 "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n", 72 run->exit_reason, 73 exit_reason_str(run->exit_reason)); 74 75 if (run->io.port == PORT_L0_EXIT) 76 break; 77 78 switch (get_ucall(vm, VCPU_ID, &uc)) { 79 case UCALL_ABORT: 80 TEST_FAIL("%s", (const char *)uc.args[0]); 81 /* NOT REACHED */ 82 default: 83 TEST_FAIL("Unknown ucall %lu", uc.cmd); 84 } 85 } 86}