2018-03-07 20:57:14 +08:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2018 Intel Corporation. All rights reserved.
|
|
|
|
*
|
2018-05-26 01:49:13 +08:00
|
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
2018-12-17 13:56:42 +08:00
|
|
|
*
|
|
|
|
* this file contains pure vmx operations
|
2018-03-07 20:57:14 +08:00
|
|
|
*/
|
|
|
|
|
2019-02-18 14:16:29 +08:00
|
|
|
#include <types.h>
|
|
|
|
#include <per_cpu.h>
|
|
|
|
#include <pgtable.h>
|
2018-09-05 13:57:15 +08:00
|
|
|
|
2018-09-05 15:13:30 +08:00
|
|
|
/**
|
|
|
|
* @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)
|
2018-03-07 20:57:14 +08:00
|
|
|
{
|
2018-09-05 15:13:30 +08:00
|
|
|
/* 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");
|
2018-03-07 20:57:14 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-09-05 15:13:30 +08:00
|
|
|
/* Per cpu data to hold the vmxon_region for each pcpu.
|
2018-06-02 11:19:30 +08:00
|
|
|
* It will be used again when we start a pcpu after the pcpu was down.
|
|
|
|
* S3 enter/exit will use it.
|
2018-12-12 20:48:57 +08:00
|
|
|
* Only run on current pcpu.
|
2018-06-02 11:19:30 +08:00
|
|
|
*/
|
2018-12-12 20:48:57 +08:00
|
|
|
void vmx_on(void)
|
2018-03-07 20:57:14 +08:00
|
|
|
{
|
2018-12-12 20:48:57 +08:00
|
|
|
uint64_t tmp64;
|
2018-03-07 20:57:14 +08:00
|
|
|
uint32_t tmp32;
|
2018-12-12 20:48:57 +08:00
|
|
|
void *vmxon_region_va = (void *)get_cpu_var(vmxon_region);
|
2018-09-05 13:51:32 +08:00
|
|
|
uint64_t vmxon_region_pa;
|
2018-03-07 20:57:14 +08:00
|
|
|
|
2018-09-05 13:51:32 +08:00
|
|
|
/* Initialize vmxon page with revision id from IA32 VMX BASIC MSR */
|
|
|
|
tmp32 = (uint32_t)msr_read(MSR_IA32_VMX_BASIC);
|
2018-12-18 15:15:45 +08:00
|
|
|
(void)memcpy_s(vmxon_region_va, 4U, (void *)&tmp32, 4U);
|
2018-03-07 20:57:14 +08:00
|
|
|
|
2018-09-05 13:51:32 +08:00
|
|
|
/* 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);
|
|
|
|
|
2018-11-06 10:05:19 +08:00
|
|
|
/* 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);
|
|
|
|
}
|
|
|
|
|
2018-09-05 13:51:32 +08:00
|
|
|
/* Turn ON VMX */
|
2018-09-06 13:50:10 +08:00
|
|
|
vmxon_region_pa = hva2hpa(vmxon_region_va);
|
2018-09-05 15:13:30 +08:00
|
|
|
exec_vmxon(&vmxon_region_pa);
|
2018-03-07 20:57:14 +08:00
|
|
|
}
|
|
|
|
|
2018-11-06 10:05:19 +08:00
|
|
|
static inline void exec_vmxoff(void)
|
|
|
|
{
|
|
|
|
asm volatile ("vmxoff" : : : "memory");
|
|
|
|
}
|
|
|
|
|
2018-09-05 15:13:30 +08:00
|
|
|
/**
|
|
|
|
* @pre addr != NULL && addr is 4KB-aligned
|
|
|
|
* @pre addr != VMXON pointer
|
|
|
|
*/
|
|
|
|
void exec_vmclear(void *addr)
|
2018-03-07 20:57:14 +08:00
|
|
|
{
|
|
|
|
|
2018-09-05 15:13:30 +08:00
|
|
|
/* pre-conditions can avoid VMfail
|
|
|
|
* here no need check RFLAGS since it will generate #GP or #UD
|
|
|
|
* except VMsuccess. SDM 30.3
|
|
|
|
*/
|
2018-03-07 20:57:14 +08:00
|
|
|
asm volatile (
|
|
|
|
"vmclear (%%rax)\n"
|
2018-09-05 15:13:30 +08:00
|
|
|
:
|
2018-07-21 22:53:10 +08:00
|
|
|
: "a"(addr)
|
|
|
|
: "cc", "memory");
|
2018-03-07 20:57:14 +08:00
|
|
|
}
|
|
|
|
|
2018-09-05 15:13:30 +08:00
|
|
|
/**
|
|
|
|
* @pre addr != NULL && addr is 4KB-aligned
|
|
|
|
* @pre addr != VMXON pointer
|
|
|
|
*/
|
|
|
|
void exec_vmptrld(void *addr)
|
2018-03-07 20:57:14 +08:00
|
|
|
{
|
2018-09-05 15:13:30 +08:00
|
|
|
/* pre-conditions can avoid VMfail
|
|
|
|
* here no need check RFLAGS since it will generate #GP or #UD
|
|
|
|
* except VMsuccess. SDM 30.3
|
|
|
|
*/
|
2018-03-07 20:57:14 +08:00
|
|
|
asm volatile (
|
|
|
|
"vmptrld (%%rax)\n"
|
2018-09-05 15:13:30 +08:00
|
|
|
:
|
2018-07-21 22:53:10 +08:00
|
|
|
: "a"(addr)
|
|
|
|
: "cc", "memory");
|
2018-03-07 20:57:14 +08:00
|
|
|
}
|
|
|
|
|
2018-12-12 20:48:57 +08:00
|
|
|
/**
|
|
|
|
* only run on current pcpu
|
|
|
|
*/
|
|
|
|
void vmx_off(void)
|
|
|
|
{
|
|
|
|
void **vmcs_ptr = &get_cpu_var(vmcs_run);
|
|
|
|
|
|
|
|
if (*vmcs_ptr != NULL) {
|
|
|
|
uint64_t vmcs_pa;
|
|
|
|
|
|
|
|
vmcs_pa = hva2hpa(*vmcs_ptr);
|
|
|
|
exec_vmclear((void *)&vmcs_pa);
|
|
|
|
*vmcs_ptr = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
exec_vmxoff();
|
|
|
|
}
|
|
|
|
|
HV:treewide:Update exec_vmread/exec_vmwrite and exec_vmread64/exec_vmwrite64
In the hypervisor, VMCS fields include 16-bit fields,
32-bit fields, 64-bit fields and natural-width fields.
In the current implement, there are exec_vmread/exec_vmwrite
used for accessing 32-bit fields, 64-bit field and
natural-width fields. This usage will confue developer.
So there are many type casting for the return value and
parameters vmread/vmwrite operations.
Since exec_vmread/exec_vmwrite and exec_vmread64/exec_vmwrite64
are the same, update current exec_vmread/exec_vmwrite
implement into exec_vmread64/exec_vmwrite64 implement
and add MACRO define for exec_vmread/exec_vmwrite in
head file;
To access 64-bit fields in VMCS, callers use
exec_vmread64/exec_vmwrite64;
Update related variables type for vmread/vmwrite operations;
Update related caller according to VMCS fields size.
Note:Natural-width fields have 64 bits on processors
that support Intel 64 architecture.To access natural-width
fields in VMCS, callers still use exec_vmread/exec_vmwrite,
keep the current implementation.
V1--V2:
This is new part of this patch serial to only
update 64-bit vmread/vmread opertions and related
caller, for netural width fields, still use exec_vmread
or exec_vmwrite.
V2-->V3:
Fix few mistake updations for netural fields in VMCS,
just keep exec_vmread/exec_vmwrite to access them;
Fix few mistake updations for 64-bit fields in VMCS.
V3--V4:
Add "016ll" for 64-bit variable in log function;
Few updates for coding style;
Rename lssd32_idx as tr_sel in VMX module.
V4-->V5:
Use CPU_NATURAL_LAST in the vm_get_register and
vm_set_register to make condition statement more
understandable.
Signed-off-by: Xiangyang Wu <xiangyang.wu@intel.com>
Reviewed-by: Junjie Mao <junjie.mao@intel.com>
2018-07-16 16:37:28 +08:00
|
|
|
uint64_t exec_vmread64(uint32_t field_full)
|
2018-03-07 20:57:14 +08:00
|
|
|
{
|
|
|
|
uint64_t value;
|
|
|
|
|
|
|
|
asm volatile (
|
|
|
|
"vmread %%rdx, %%rax "
|
|
|
|
: "=a" (value)
|
HV:treewide:Update exec_vmread/exec_vmwrite and exec_vmread64/exec_vmwrite64
In the hypervisor, VMCS fields include 16-bit fields,
32-bit fields, 64-bit fields and natural-width fields.
In the current implement, there are exec_vmread/exec_vmwrite
used for accessing 32-bit fields, 64-bit field and
natural-width fields. This usage will confue developer.
So there are many type casting for the return value and
parameters vmread/vmwrite operations.
Since exec_vmread/exec_vmwrite and exec_vmread64/exec_vmwrite64
are the same, update current exec_vmread/exec_vmwrite
implement into exec_vmread64/exec_vmwrite64 implement
and add MACRO define for exec_vmread/exec_vmwrite in
head file;
To access 64-bit fields in VMCS, callers use
exec_vmread64/exec_vmwrite64;
Update related variables type for vmread/vmwrite operations;
Update related caller according to VMCS fields size.
Note:Natural-width fields have 64 bits on processors
that support Intel 64 architecture.To access natural-width
fields in VMCS, callers still use exec_vmread/exec_vmwrite,
keep the current implementation.
V1--V2:
This is new part of this patch serial to only
update 64-bit vmread/vmread opertions and related
caller, for netural width fields, still use exec_vmread
or exec_vmwrite.
V2-->V3:
Fix few mistake updations for netural fields in VMCS,
just keep exec_vmread/exec_vmwrite to access them;
Fix few mistake updations for 64-bit fields in VMCS.
V3--V4:
Add "016ll" for 64-bit variable in log function;
Few updates for coding style;
Rename lssd32_idx as tr_sel in VMX module.
V4-->V5:
Use CPU_NATURAL_LAST in the vm_get_register and
vm_set_register to make condition statement more
understandable.
Signed-off-by: Xiangyang Wu <xiangyang.wu@intel.com>
Reviewed-by: Junjie Mao <junjie.mao@intel.com>
2018-07-16 16:37:28 +08:00
|
|
|
: "d"(field_full)
|
2018-03-07 20:57:14 +08:00
|
|
|
: "cc");
|
|
|
|
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2018-07-16 15:43:25 +08:00
|
|
|
uint32_t exec_vmread32(uint32_t field)
|
|
|
|
{
|
|
|
|
uint64_t value;
|
|
|
|
|
|
|
|
value = exec_vmread64(field);
|
|
|
|
|
|
|
|
return (uint32_t)value;
|
|
|
|
}
|
|
|
|
|
2018-07-16 15:21:44 +08:00
|
|
|
uint16_t exec_vmread16(uint32_t field)
|
|
|
|
{
|
|
|
|
uint64_t value;
|
|
|
|
|
|
|
|
value = exec_vmread64(field);
|
|
|
|
|
|
|
|
return (uint16_t)value;
|
|
|
|
}
|
|
|
|
|
HV:treewide:Update exec_vmread/exec_vmwrite and exec_vmread64/exec_vmwrite64
In the hypervisor, VMCS fields include 16-bit fields,
32-bit fields, 64-bit fields and natural-width fields.
In the current implement, there are exec_vmread/exec_vmwrite
used for accessing 32-bit fields, 64-bit field and
natural-width fields. This usage will confue developer.
So there are many type casting for the return value and
parameters vmread/vmwrite operations.
Since exec_vmread/exec_vmwrite and exec_vmread64/exec_vmwrite64
are the same, update current exec_vmread/exec_vmwrite
implement into exec_vmread64/exec_vmwrite64 implement
and add MACRO define for exec_vmread/exec_vmwrite in
head file;
To access 64-bit fields in VMCS, callers use
exec_vmread64/exec_vmwrite64;
Update related variables type for vmread/vmwrite operations;
Update related caller according to VMCS fields size.
Note:Natural-width fields have 64 bits on processors
that support Intel 64 architecture.To access natural-width
fields in VMCS, callers still use exec_vmread/exec_vmwrite,
keep the current implementation.
V1--V2:
This is new part of this patch serial to only
update 64-bit vmread/vmread opertions and related
caller, for netural width fields, still use exec_vmread
or exec_vmwrite.
V2-->V3:
Fix few mistake updations for netural fields in VMCS,
just keep exec_vmread/exec_vmwrite to access them;
Fix few mistake updations for 64-bit fields in VMCS.
V3--V4:
Add "016ll" for 64-bit variable in log function;
Few updates for coding style;
Rename lssd32_idx as tr_sel in VMX module.
V4-->V5:
Use CPU_NATURAL_LAST in the vm_get_register and
vm_set_register to make condition statement more
understandable.
Signed-off-by: Xiangyang Wu <xiangyang.wu@intel.com>
Reviewed-by: Junjie Mao <junjie.mao@intel.com>
2018-07-16 16:37:28 +08:00
|
|
|
void exec_vmwrite64(uint32_t field_full, uint64_t value)
|
2018-03-07 20:57:14 +08:00
|
|
|
{
|
|
|
|
asm volatile (
|
|
|
|
"vmwrite %%rax, %%rdx "
|
HV:treewide:Update exec_vmread/exec_vmwrite and exec_vmread64/exec_vmwrite64
In the hypervisor, VMCS fields include 16-bit fields,
32-bit fields, 64-bit fields and natural-width fields.
In the current implement, there are exec_vmread/exec_vmwrite
used for accessing 32-bit fields, 64-bit field and
natural-width fields. This usage will confue developer.
So there are many type casting for the return value and
parameters vmread/vmwrite operations.
Since exec_vmread/exec_vmwrite and exec_vmread64/exec_vmwrite64
are the same, update current exec_vmread/exec_vmwrite
implement into exec_vmread64/exec_vmwrite64 implement
and add MACRO define for exec_vmread/exec_vmwrite in
head file;
To access 64-bit fields in VMCS, callers use
exec_vmread64/exec_vmwrite64;
Update related variables type for vmread/vmwrite operations;
Update related caller according to VMCS fields size.
Note:Natural-width fields have 64 bits on processors
that support Intel 64 architecture.To access natural-width
fields in VMCS, callers still use exec_vmread/exec_vmwrite,
keep the current implementation.
V1--V2:
This is new part of this patch serial to only
update 64-bit vmread/vmread opertions and related
caller, for netural width fields, still use exec_vmread
or exec_vmwrite.
V2-->V3:
Fix few mistake updations for netural fields in VMCS,
just keep exec_vmread/exec_vmwrite to access them;
Fix few mistake updations for 64-bit fields in VMCS.
V3--V4:
Add "016ll" for 64-bit variable in log function;
Few updates for coding style;
Rename lssd32_idx as tr_sel in VMX module.
V4-->V5:
Use CPU_NATURAL_LAST in the vm_get_register and
vm_set_register to make condition statement more
understandable.
Signed-off-by: Xiangyang Wu <xiangyang.wu@intel.com>
Reviewed-by: Junjie Mao <junjie.mao@intel.com>
2018-07-16 16:37:28 +08:00
|
|
|
: : "a" (value), "d"(field_full)
|
2018-03-07 20:57:14 +08:00
|
|
|
: "cc");
|
|
|
|
}
|
|
|
|
|
2018-07-16 15:43:25 +08:00
|
|
|
void exec_vmwrite32(uint32_t field, uint32_t value)
|
|
|
|
{
|
|
|
|
exec_vmwrite64(field, (uint64_t)value);
|
|
|
|
}
|
|
|
|
|
2018-07-16 15:21:44 +08:00
|
|
|
void exec_vmwrite16(uint32_t field, uint16_t value)
|
|
|
|
{
|
|
|
|
exec_vmwrite64(field, (uint64_t)value);
|
|
|
|
}
|