tools/testing/selftests/kvm/lib/x86/vmx.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/kvm/lib/x86/vmx.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/kvm/lib/x86/vmx.c
Extension
.c
Size
12396 bytes
Lines
397
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) 2018, Google LLC.
 */

#include <asm/msr-index.h>

#include "test_util.h"
#include "kvm_util.h"
#include "processor.h"
#include "vmx.h"

#define KVM_EPT_PAGE_TABLE_MIN_PADDR 0x1c0000

#define EPTP_MT_SHIFT		0 /* EPTP memtype bits 2:0 */
#define EPTP_PWL_SHIFT		3 /* EPTP page walk length bits 5:3 */
#define EPTP_AD_ENABLED_SHIFT	6 /* EPTP AD enabled bit 6 */

#define EPTP_WB			(X86_MEMTYPE_WB << EPTP_MT_SHIFT)
#define EPTP_PWL_4		(3ULL << EPTP_PWL_SHIFT) /* PWL is (levels - 1) */
#define EPTP_AD_ENABLED		(1ULL << EPTP_AD_ENABLED_SHIFT)

bool enable_evmcs;

struct hv_enlightened_vmcs *current_evmcs;
struct hv_vp_assist_page *current_vp_assist;

int vcpu_enable_evmcs(struct kvm_vcpu *vcpu)
{
	u16 evmcs_ver;

	vcpu_enable_cap(vcpu, KVM_CAP_HYPERV_ENLIGHTENED_VMCS,
			(unsigned long)&evmcs_ver);

	/* KVM should return supported EVMCS version range */
	TEST_ASSERT(((evmcs_ver >> 8) >= (evmcs_ver & 0xff)) &&
		    (evmcs_ver & 0xff) > 0,
		    "Incorrect EVMCS version range: %x:%x",
		    evmcs_ver & 0xff, evmcs_ver >> 8);

	return evmcs_ver;
}

void vm_enable_ept(struct kvm_vm *vm)
{
	struct pte_masks pte_masks;

	TEST_ASSERT(kvm_cpu_has_ept(), "KVM doesn't support nested EPT");

	/*
	 * EPTs do not have 'present' or 'user' bits, instead bit 0 is the
	 * 'readable' bit.
	 */
	pte_masks = (struct pte_masks) {
		.present	=	0,
		.user		=	0,
		.readable	=	BIT_ULL(0),
		.writable	=	BIT_ULL(1),
		.executable	=	BIT_ULL(2),
		.huge		=	BIT_ULL(7),
		.accessed	=	BIT_ULL(8),
		.dirty		=	BIT_ULL(9),
		.nx		=	0,
	};

	/* TODO: Add support for 5-level EPT. */
	tdp_mmu_init(vm, 4, &pte_masks);
}

/* Allocate memory regions for nested VMX tests.
 *
 * Input Args:
 *   vm - The VM to allocate guest-virtual addresses in.
 *
 * Output Args:
 *   p_vmx_gva - The guest virtual address for the struct vmx_pages.
 *
 * Return:
 *   Pointer to structure with the addresses of the VMX areas.
 */
struct vmx_pages *
vcpu_alloc_vmx(struct kvm_vm *vm, gva_t *p_vmx_gva)
{
	gva_t vmx_gva = vm_alloc_page(vm);
	struct vmx_pages *vmx = addr_gva2hva(vm, vmx_gva);

	/* Setup of a region of guest memory for the vmxon region. */
	vmx->vmxon = (void *)vm_alloc_page(vm);
	vmx->vmxon_hva = addr_gva2hva(vm, (uintptr_t)vmx->vmxon);
	vmx->vmxon_gpa = addr_gva2gpa(vm, (uintptr_t)vmx->vmxon);

Annotation

Implementation Notes