File Index
Files and directories
Sign in
FILE

vmx_invalid_nested_guest_state.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/kvm/x86/vmx_invalid_nested_guest_state.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2#include "test_util.h"
  3#include "kvm_util.h"
  4#include "processor.h"
  5#include "vmx.h"
  6
  7#include <string.h>
  8#include <sys/ioctl.h>
  9
 10#include "kselftest.h"
 11
 12#define ARBITRARY_IO_PORT 0x2000
 13
 14static struct kvm_vm *vm;
 15
 16static void l2_guest_code(void)
 17{
 18	/*
 19	 * Generate an exit to L0 userspace, i.e. main(), via I/O to an
 20	 * arbitrary port.
 21	 */
 22	asm volatile("inb %%dx, %%al"
 23		     : : [port] "d" (ARBITRARY_IO_PORT) : "rax");
 24}
 25
 26static void l1_guest_code(struct vmx_pages *vmx_pages)
 27{
 28#define L2_GUEST_STACK_SIZE 64
 29	unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE];
 30
 31	GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages));
 32	GUEST_ASSERT(load_vmcs(vmx_pages));
 33
 34	/* Prepare the VMCS for L2 execution. */
 35	prepare_vmcs(vmx_pages, l2_guest_code,
 36		     &l2_guest_stack[L2_GUEST_STACK_SIZE]);
 37
 38	/*
 39	 * L2 must be run without unrestricted guest, verify that the selftests
 40	 * library hasn't enabled it.  Because KVM selftests jump directly to
 41	 * 64-bit mode, unrestricted guest support isn't required.
 42	 */
 43	GUEST_ASSERT(!(vmreadz(CPU_BASED_VM_EXEC_CONTROL) & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS) ||
 44		     !(vmreadz(SECONDARY_VM_EXEC_CONTROL) & SECONDARY_EXEC_UNRESTRICTED_GUEST));
 45
 46	GUEST_ASSERT(!vmlaunch());
 47
 48	/* L2 should triple fault after main() stuffs invalid guest state. */
 49	GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_TRIPLE_FAULT);
 50	GUEST_DONE();
 51}
 52
 53int main(int argc, char *argv[])
 54{
 55	vm_vaddr_t vmx_pages_gva;
 56	struct kvm_sregs sregs;
 57	struct kvm_vcpu *vcpu;
 58	struct kvm_run *run;
 59	struct ucall uc;
 60
 61	TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX));
 62
 63	vm = vm_create_with_one_vcpu(&vcpu, l1_guest_code);
 64
 65	/* Allocate VMX pages and shared descriptors (vmx_pages). */
 66	vcpu_alloc_vmx(vm, &vmx_pages_gva);
 67	vcpu_args_set(vcpu, 1, vmx_pages_gva);
 68
 69	vcpu_run(vcpu);
 70
 71	run = vcpu->run;
 72
 73	/*
 74	 * The first exit to L0 userspace should be an I/O access from L2.
 75	 * Running L1 should launch L2 without triggering an exit to userspace.
 76	 */
 77	TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 78
 79	TEST_ASSERT(run->io.port == ARBITRARY_IO_PORT,
 80		    "Expected IN from port %d from L2, got port %d",
 81		    ARBITRARY_IO_PORT, run->io.port);
 82
 83	/*
 84	 * Stuff invalid guest state for L2 by making TR unusuable.  The next
 85	 * KVM_RUN should induce a TRIPLE_FAULT in L2 as KVM doesn't support
 86	 * emulating invalid guest state for L2.
 87	 */
 88	memset(&sregs, 0, sizeof(sregs));
 89	vcpu_sregs_get(vcpu, &sregs);
 90	sregs.tr.unusable = 1;
 91	vcpu_sregs_set(vcpu, &sregs);
 92
 93	vcpu_run(vcpu);
 94
 95	switch (get_ucall(vcpu, &uc)) {
 96	case UCALL_DONE:
 97		break;
 98	case UCALL_ABORT:
 99		REPORT_GUEST_ASSERT(uc);
100	default:
101		TEST_FAIL("Unexpected ucall: %lu", uc.cmd);
102	}
103}
~/ Read-only file preview.