HV:treewide: Add exec_vmread16 and exec_vmwrite16 functions

In the hypervisor, VMCS fields include 16-bit fields,
32-bit fields, 64-bit fields and natural-width fields.
In the current implement, no exec_vmread16/exec_vmwrite16
is for accessing 16-bit fields. So there are many type
casting for the return value and parameters vmread/vmwrite
operations.

Create exec_vmread16 and exec_vmwrite16 functions to
access 16-bit fields in VMCS;
Update related variables type for vmread/vmwrite operations;
Update related caller according to VMCS fields size.

V1--V2:
	This is new part of this patch serial to only
	update 16-bit vmread/vmread opertions and related
	caller.
V2--V3:
	Add "hu" for uint16_t argument in log function;
	Add comments for function get_vmcs_field;
	Update related variables type for exec_vmread16;
	Rename temp variable 'low' into 'value'.
V3-->V4:
	Few updates for exec_vmread16.
V4-->V5:
	Few updates for coding style;
	Replace "hux" with "hu" in log function for 16-bit
	variable.
V5-->V6:
	CPU_REG_64BIT_LAST is used 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>
This commit is contained in:
Xiangyang Wu
2018-07-16 15:21:44 +08:00
committed by lijinxia
parent d3b9712438
commit 65437960a9
8 changed files with 83 additions and 45 deletions

View File

@@ -286,7 +286,7 @@ int gva2gpa(struct vcpu *vcpu, uint64_t gva, uint64_t *gpa,
pw_info.level = pm;
pw_info.is_write_access = ((*err_code & PAGE_FAULT_WR_FLAG) != 0U);
pw_info.is_inst_fetch = ((*err_code & PAGE_FAULT_ID_FLAG) != 0U);
pw_info.is_user_mode = ((exec_vmread(VMX_GUEST_CS_SEL) & 0x3UL) == 3UL);
pw_info.is_user_mode = ((exec_vmread16(VMX_GUEST_CS_SEL) & 0x3U) == 3U);
pw_info.pse = true;
pw_info.nxe =
((cur_context->ia32_efer & MSR_IA32_EFER_NXE_BIT) != 0UL);

View File

@@ -44,7 +44,11 @@ int vm_get_register(struct vcpu *vcpu, enum cpu_reg_name reg, uint64_t *retval)
uint32_t field = get_vmcs_field(reg);
if (field != VMX_INVALID_VMCS_FIELD) {
*retval = exec_vmread(field);
if (reg < CPU_REG_64BIT_LAST) {
*retval = exec_vmread(field);
} else {
*retval = (uint64_t)exec_vmread16(field);
}
} else {
return -EINVAL;
}
@@ -73,7 +77,11 @@ int vm_set_register(struct vcpu *vcpu, enum cpu_reg_name reg, uint64_t val)
uint32_t field = get_vmcs_field(reg);
if (field != VMX_INVALID_VMCS_FIELD) {
exec_vmwrite(field, val);
if (reg < CPU_REG_64BIT_LAST) {
exec_vmwrite(field, val);
} else {
exec_vmwrite16(field, (uint16_t)val);
}
} else {
return -EINVAL;
}
@@ -223,7 +231,21 @@ encode_vmcs_seg_desc(enum cpu_reg_name seg,
return 0;
}
/**
*
*Description:
*This local function is to covert register names into
*the corresponding field index MACROs in VMCS.
*
*Post Condition:
*In the non-general register names group (CPU_REG_CR0~CPU_REG_LAST),
*for register names CPU_REG_CR2, CPU_REG_IDTR, CPU_REG_GDTR,
*CPU_REG_NATURAL_LAST, CPU_REG_64BIT_LAST and CPU_REG_LAST,
*this function returns VMX_INVALID_VMCS_FIELD;
*for other register names, it returns correspoding field index MACROs
*in VMCS.
*
**/
static uint32_t get_vmcs_field(enum cpu_reg_name ident)
{
switch (ident) {

View File

@@ -158,7 +158,7 @@ int start_vcpu(struct vcpu *vcpu)
vcpu->vm->attr.id, vcpu->vcpu_id);
if (vcpu->arch_vcpu.vpid)
exec_vmwrite(VMX_VPID, vcpu->arch_vcpu.vpid);
exec_vmwrite16(VMX_VPID, vcpu->arch_vcpu.vpid);
/*
* A power-up or a reset invalidates all linear mappings,

View File

@@ -2340,13 +2340,12 @@ apicv_inject_pir(struct vlapic *vlapic)
if (pirval != 0UL) {
rvi = pirbase + fls64(pirval);
intr_status_old = (uint16_t)
(0xFFFFUL &
exec_vmread(VMX_GUEST_INTR_STATUS));
intr_status_old = 0xFFFFU &
exec_vmread16(VMX_GUEST_INTR_STATUS);
intr_status_new = (intr_status_old & 0xFF00U) | rvi;
if (intr_status_new > intr_status_old) {
exec_vmwrite(VMX_GUEST_INTR_STATUS,
exec_vmwrite16(VMX_GUEST_INTR_STATUS,
intr_status_new);
}
}