acrn-hypervisor/hypervisor/arch/x86/vmx.c
Geoffroy Van Cutsem 8b16be9185 Remove "All rights reserved" string headers
Many of the license and Intel copyright headers include the "All rights
reserved" string. It is not relevant in the context of the BSD-3-Clause
license that the code is released under. This patch removes those strings
throughout the code (hypervisor, devicemodel and misc).

Tracked-On: #7254
Signed-off-by: Geoffroy Van Cutsem <geoffroy.vancutsem@intel.com>
2022-04-06 13:21:02 +08:00

197 lines
3.8 KiB
C

/*
* Copyright (C) 2018 Intel Corporation.
*
* SPDX-License-Identifier: BSD-3-Clause
*
* this file contains pure vmx operations
*/
#include <types.h>
#include <asm/msr.h>
#include <asm/per_cpu.h>
#include <asm/pgtable.h>
#include <asm/vmx.h>
/**
* @pre addr != NULL && addr is 4KB-aligned
* rev[31:0] 32 bits located at vmxon region physical address
* @pre rev[30:0] == VMCS revision && rev[31] == 0
*/
static inline void exec_vmxon(void *addr)
{
/* Turn VMX on, pre-conditions can avoid VMfailInvalid
* here no need check RFLAGS since it will generate #GP or #UD
* except VMsuccess. SDM 30.3
*/
asm volatile (
"vmxon (%%rax)\n"
:
: "a"(addr)
: "cc", "memory");
}
/* Per cpu data to hold the vmxon_region for each pcpu.
* It will be used again when we start a pcpu after the pcpu was down.
* S3 enter/exit will use it.
* Only run on current pcpu.
*/
void vmx_on(void)
{
uint64_t tmp64;
uint32_t tmp32;
void *vmxon_region_va = (void *)get_cpu_var(vmxon_region);
uint64_t vmxon_region_pa;
/* Initialize vmxon page with revision id from IA32 VMX BASIC MSR */
tmp32 = (uint32_t)msr_read(MSR_IA32_VMX_BASIC);
(void)memcpy_s(vmxon_region_va, 4U, (void *)&tmp32, 4U);
/* Turn on CR0.NE and CR4.VMXE */
CPU_CR_READ(cr0, &tmp64);
CPU_CR_WRITE(cr0, tmp64 | CR0_NE);
CPU_CR_READ(cr4, &tmp64);
CPU_CR_WRITE(cr4, tmp64 | CR4_VMXE);
/* Read Feature ControL MSR */
tmp64 = msr_read(MSR_IA32_FEATURE_CONTROL);
/* Check if feature control is locked */
if ((tmp64 & MSR_IA32_FEATURE_CONTROL_LOCK) == 0U) {
/* Lock and enable VMX support */
tmp64 |= (MSR_IA32_FEATURE_CONTROL_LOCK |
MSR_IA32_FEATURE_CONTROL_VMX_NO_SMX);
msr_write(MSR_IA32_FEATURE_CONTROL, tmp64);
}
/* Turn ON VMX */
vmxon_region_pa = hva2hpa(vmxon_region_va);
exec_vmxon(&vmxon_region_pa);
}
static inline void exec_vmxoff(void)
{
asm volatile ("vmxoff" : : : "memory");
}
/**
* @pre addr != NULL && addr is 4KB-aligned
* @pre addr != VMXON pointer
*/
void exec_vmclear(void *addr)
{
/* pre-conditions can avoid VMfail
* here no need check RFLAGS since it will generate #GP or #UD
* except VMsuccess. SDM 30.3
*/
asm volatile (
"vmclear (%%rax)\n"
:
: "a"(addr)
: "cc", "memory");
}
/**
* @pre addr != NULL && addr is 4KB-aligned
* @pre addr != VMXON pointer
*/
void exec_vmptrld(void *addr)
{
/* pre-conditions can avoid VMfail
* here no need check RFLAGS since it will generate #GP or #UD
* except VMsuccess. SDM 30.3
*/
asm volatile (
"vmptrld (%%rax)\n"
:
: "a"(addr)
: "cc", "memory");
}
/*
* @pre vcpu != NULL
*/
void load_va_vmcs(const uint8_t *vmcs_va)
{
uint64_t vmcs_pa;
vmcs_pa = hva2hpa(vmcs_va);
exec_vmptrld((void *)&vmcs_pa);
}
/*
* @pre vcpu != NULL
*/
void clear_va_vmcs(const uint8_t *vmcs_va)
{
uint64_t vmcs_pa;
vmcs_pa = hva2hpa(vmcs_va);
exec_vmclear((void *)&vmcs_pa);
}
/**
* only run on current pcpu
*/
void vmx_off(void)
{
void **vmcs_ptr = &get_cpu_var(vmcs_run);
if (*vmcs_ptr != NULL) {
clear_va_vmcs(*vmcs_ptr);
*vmcs_ptr = NULL;
}
exec_vmxoff();
}
uint64_t exec_vmread64(uint32_t field_full)
{
uint64_t value;
asm volatile (
"vmread %%rdx, %%rax "
: "=a" (value)
: "d"(field_full)
: "cc");
return value;
}
uint32_t exec_vmread32(uint32_t field)
{
uint64_t value;
value = exec_vmread64(field);
return (uint32_t)value;
}
uint16_t exec_vmread16(uint32_t field)
{
uint64_t value;
value = exec_vmread64(field);
return (uint16_t)value;
}
void exec_vmwrite64(uint32_t field_full, uint64_t value)
{
asm volatile (
"vmwrite %%rax, %%rdx "
: : "a" (value), "d"(field_full)
: "cc");
}
void exec_vmwrite32(uint32_t field, uint32_t value)
{
exec_vmwrite64(field, (uint64_t)value);
}
void exec_vmwrite16(uint32_t field, uint16_t value)
{
exec_vmwrite64(field, (uint64_t)value);
}