mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-23 14:07:42 +00:00
HV: instr_emul: Make vm_set/get_register as non-failed function
Originally, vm_set/get_register return -EINVAL when "vcpu == NULL" or reg is invalid. But, we don't check the return value actually and there is no chance we get an null-vcpu and invalid reg in current implementation. This patch add pre-assumptions about valid parameters before the function and make them as non-failed functions. - static uint64_t vm_get_register(struct vcpu *vcpu, enum cpu_reg_name reg) - static void vm_set_register(struct vcpu *vcpu, enum cpu_reg_name reg, uint64_t val) Signed-off-by: Kaige Fu <kaige.fu@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
b6b7e75ee4
commit
59c0f355c8
@ -306,54 +306,46 @@ static uint32_t get_vmcs_field(enum cpu_reg_name ident)
|
|||||||
return VMX_GUEST_PDPTE2_FULL;
|
return VMX_GUEST_PDPTE2_FULL;
|
||||||
case CPU_REG_PDPTE3:
|
case CPU_REG_PDPTE3:
|
||||||
return VMX_GUEST_PDPTE3_FULL;
|
return VMX_GUEST_PDPTE3_FULL;
|
||||||
default:
|
default: /* Never get here */
|
||||||
return VMX_INVALID_VMCS_FIELD;
|
return VMX_INVALID_VMCS_FIELD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vm_get_register(struct vcpu *vcpu, enum cpu_reg_name reg,
|
/**
|
||||||
uint64_t *retval)
|
* @pre vcpu != NULL
|
||||||
|
* @pre ((reg <= CPU_REG_LAST) && (reg >= CPU_REG_FIRST))
|
||||||
|
* @pre ((reg != CPU_REG_CR2) && (reg != CPU_REG_IDTR) && (reg != CPU_REG_GDTR))
|
||||||
|
*/
|
||||||
|
static uint64_t vm_get_register(struct vcpu *vcpu, enum cpu_reg_name reg)
|
||||||
{
|
{
|
||||||
if (vcpu == NULL) {
|
uint64_t reg_val;
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((reg > CPU_REG_LAST) || (reg < CPU_REG_FIRST)) {
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((reg >= CPU_REG_GENERAL_FIRST) && (reg <= CPU_REG_GENERAL_LAST)) {
|
if ((reg >= CPU_REG_GENERAL_FIRST) && (reg <= CPU_REG_GENERAL_LAST)) {
|
||||||
*retval = vcpu_get_gpreg(vcpu, reg);
|
reg_val = vcpu_get_gpreg(vcpu, reg);
|
||||||
} else if ((reg >= CPU_REG_NONGENERAL_FIRST) &&
|
} else if ((reg >= CPU_REG_NONGENERAL_FIRST) &&
|
||||||
(reg <= CPU_REG_NONGENERAL_LAST)) {
|
(reg <= CPU_REG_NONGENERAL_LAST)) {
|
||||||
uint32_t field = get_vmcs_field(reg);
|
uint32_t field = get_vmcs_field(reg);
|
||||||
|
|
||||||
if (field != VMX_INVALID_VMCS_FIELD) {
|
|
||||||
if (reg <= CPU_REG_NATURAL_LAST) {
|
if (reg <= CPU_REG_NATURAL_LAST) {
|
||||||
*retval = exec_vmread(field);
|
reg_val = exec_vmread(field);
|
||||||
} else if (reg <= CPU_REG_64BIT_LAST) {
|
} else if (reg <= CPU_REG_64BIT_LAST) {
|
||||||
*retval = exec_vmread64(field);
|
reg_val = exec_vmread64(field);
|
||||||
} else {
|
} else {
|
||||||
*retval = (uint64_t)exec_vmread16(field);
|
reg_val = (uint64_t)exec_vmread16(field);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return reg_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vm_set_register(struct vcpu *vcpu, enum cpu_reg_name reg,
|
/**
|
||||||
|
* @pre vcpu != NULL
|
||||||
|
* @pre ((reg <= CPU_REG_LAST) && (reg >= CPU_REG_FIRST))
|
||||||
|
* @pre ((reg != CPU_REG_CR2) && (reg != CPU_REG_IDTR) && (reg != CPU_REG_GDTR))
|
||||||
|
*/
|
||||||
|
static void vm_set_register(struct vcpu *vcpu, enum cpu_reg_name reg,
|
||||||
uint64_t val)
|
uint64_t val)
|
||||||
{
|
{
|
||||||
if (vcpu == NULL) {
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((reg > CPU_REG_LAST) || (reg < CPU_REG_FIRST)) {
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((reg >= CPU_REG_GENERAL_FIRST) && (reg <= CPU_REG_GENERAL_LAST)) {
|
if ((reg >= CPU_REG_GENERAL_FIRST) && (reg <= CPU_REG_GENERAL_LAST)) {
|
||||||
vcpu_set_gpreg(vcpu, reg, val);
|
vcpu_set_gpreg(vcpu, reg, val);
|
||||||
@ -361,7 +353,6 @@ static int vm_set_register(struct vcpu *vcpu, enum cpu_reg_name reg,
|
|||||||
(reg <= CPU_REG_NONGENERAL_LAST)) {
|
(reg <= CPU_REG_NONGENERAL_LAST)) {
|
||||||
uint32_t field = get_vmcs_field(reg);
|
uint32_t field = get_vmcs_field(reg);
|
||||||
|
|
||||||
if (field != VMX_INVALID_VMCS_FIELD) {
|
|
||||||
if (reg <= CPU_REG_NATURAL_LAST) {
|
if (reg <= CPU_REG_NATURAL_LAST) {
|
||||||
exec_vmwrite(field, val);
|
exec_vmwrite(field, val);
|
||||||
} else if (reg <= CPU_REG_64BIT_LAST) {
|
} else if (reg <= CPU_REG_64BIT_LAST) {
|
||||||
@ -369,14 +360,9 @@ static int vm_set_register(struct vcpu *vcpu, enum cpu_reg_name reg,
|
|||||||
} else {
|
} else {
|
||||||
exec_vmwrite16(field, (uint16_t)val);
|
exec_vmwrite16(field, (uint16_t)val);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @pre vcpu != NULL
|
* @pre vcpu != NULL
|
||||||
* @pre desc != NULL
|
* @pre desc != NULL
|
||||||
@ -615,11 +601,11 @@ static int vie_read_bytereg(struct vcpu *vcpu, struct instr_emul_vie *vie,
|
|||||||
uint8_t *rval)
|
uint8_t *rval)
|
||||||
{
|
{
|
||||||
uint64_t val;
|
uint64_t val;
|
||||||
int error, lhbr;
|
int error = 0, lhbr;
|
||||||
enum cpu_reg_name reg;
|
enum cpu_reg_name reg;
|
||||||
|
|
||||||
vie_calc_bytereg(vie, ®, &lhbr);
|
vie_calc_bytereg(vie, ®, &lhbr);
|
||||||
error = vm_get_register(vcpu, reg, &val);
|
val = vm_get_register(vcpu, reg);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* To obtain the value of a legacy high byte register shift the
|
* To obtain the value of a legacy high byte register shift the
|
||||||
@ -637,11 +623,11 @@ static int vie_write_bytereg(struct vcpu *vcpu, struct instr_emul_vie *vie,
|
|||||||
uint8_t byte)
|
uint8_t byte)
|
||||||
{
|
{
|
||||||
uint64_t origval, val, mask;
|
uint64_t origval, val, mask;
|
||||||
int error, lhbr;
|
int error = 0, lhbr;
|
||||||
enum cpu_reg_name reg;
|
enum cpu_reg_name reg;
|
||||||
|
|
||||||
vie_calc_bytereg(vie, ®, &lhbr);
|
vie_calc_bytereg(vie, ®, &lhbr);
|
||||||
error = vm_get_register(vcpu, reg, &origval);
|
origval = vm_get_register(vcpu, reg);
|
||||||
if (error == 0) {
|
if (error == 0) {
|
||||||
val = byte;
|
val = byte;
|
||||||
mask = 0xffU;
|
mask = 0xffU;
|
||||||
@ -654,7 +640,7 @@ static int vie_write_bytereg(struct vcpu *vcpu, struct instr_emul_vie *vie,
|
|||||||
mask <<= 8;
|
mask <<= 8;
|
||||||
}
|
}
|
||||||
val |= origval & ~mask;
|
val |= origval & ~mask;
|
||||||
error = vm_set_register(vcpu, reg, val);
|
vm_set_register(vcpu, reg, val);
|
||||||
}
|
}
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@ -662,17 +648,14 @@ static int vie_write_bytereg(struct vcpu *vcpu, struct instr_emul_vie *vie,
|
|||||||
static int vie_update_register(struct vcpu *vcpu, enum cpu_reg_name reg,
|
static int vie_update_register(struct vcpu *vcpu, enum cpu_reg_name reg,
|
||||||
uint64_t val_arg, uint8_t size)
|
uint64_t val_arg, uint8_t size)
|
||||||
{
|
{
|
||||||
int error;
|
int error = 0;
|
||||||
uint64_t origval;
|
uint64_t origval;
|
||||||
uint64_t val = val_arg;
|
uint64_t val = val_arg;
|
||||||
|
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case 1U:
|
case 1U:
|
||||||
case 2U:
|
case 2U:
|
||||||
error = vm_get_register(vcpu, reg, &origval);
|
origval = vm_get_register(vcpu, reg);
|
||||||
if (error != 0) {
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
val &= size2mask[size];
|
val &= size2mask[size];
|
||||||
val |= origval & ~size2mask[size];
|
val |= origval & ~size2mask[size];
|
||||||
break;
|
break;
|
||||||
@ -685,7 +668,7 @@ static int vie_update_register(struct vcpu *vcpu, enum cpu_reg_name reg,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = vm_set_register(vcpu, reg, val);
|
vm_set_register(vcpu, reg, val);
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@ -694,14 +677,11 @@ static int vie_update_register(struct vcpu *vcpu, enum cpu_reg_name reg,
|
|||||||
|
|
||||||
static int vie_update_rflags(struct vcpu *vcpu, uint64_t rflags2, uint64_t psl)
|
static int vie_update_rflags(struct vcpu *vcpu, uint64_t rflags2, uint64_t psl)
|
||||||
{
|
{
|
||||||
int error;
|
int error = 0;
|
||||||
uint8_t size;
|
uint8_t size;
|
||||||
uint64_t rflags;
|
uint64_t rflags;
|
||||||
|
|
||||||
error = vm_get_register(vcpu, CPU_REG_RFLAGS, &rflags);
|
rflags = vm_get_register(vcpu, CPU_REG_RFLAGS);
|
||||||
if (error != 0) {
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
rflags &= ~RFLAGS_STATUS_BITS;
|
rflags &= ~RFLAGS_STATUS_BITS;
|
||||||
rflags |= rflags2 & psl;
|
rflags |= rflags2 & psl;
|
||||||
@ -778,11 +758,9 @@ static int emulate_mov(struct vcpu *vcpu, struct instr_emul_vie *vie)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
reg = vie->reg;
|
reg = vie->reg;
|
||||||
error = vm_get_register(vcpu, reg, &val);
|
val = vm_get_register(vcpu, reg);
|
||||||
if (error == 0) {
|
|
||||||
val &= size2mask[size];
|
val &= size2mask[size];
|
||||||
error = mmio_write(vcpu, val);
|
error = mmio_write(vcpu, val);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 0x8AU:
|
case 0x8AU:
|
||||||
/*
|
/*
|
||||||
@ -831,12 +809,9 @@ static int emulate_mov(struct vcpu *vcpu, struct instr_emul_vie *vie)
|
|||||||
* A3: mov moffs32, EAX
|
* A3: mov moffs32, EAX
|
||||||
* REX.W + A3: mov moffs64, RAX
|
* REX.W + A3: mov moffs64, RAX
|
||||||
*/
|
*/
|
||||||
error = vm_get_register(vcpu, CPU_REG_RAX,
|
val = vm_get_register(vcpu, CPU_REG_RAX);
|
||||||
&val);
|
|
||||||
if (error == 0) {
|
|
||||||
val &= size2mask[size];
|
val &= size2mask[size];
|
||||||
error = mmio_write(vcpu, val);
|
error = mmio_write(vcpu, val);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 0xC6U:
|
case 0xC6U:
|
||||||
/*
|
/*
|
||||||
@ -962,19 +937,12 @@ static int get_gla(struct vcpu *vcpu, __unused struct instr_emul_vie *vie,
|
|||||||
{
|
{
|
||||||
struct seg_desc desc;
|
struct seg_desc desc;
|
||||||
uint64_t cr0, val, rflags;
|
uint64_t cr0, val, rflags;
|
||||||
int error;
|
|
||||||
|
|
||||||
error = vm_get_register(vcpu, CPU_REG_CR0, &cr0);
|
cr0 = vm_get_register(vcpu, CPU_REG_CR0);
|
||||||
error |= vm_get_register(vcpu, CPU_REG_RFLAGS, &rflags);
|
rflags = vm_get_register(vcpu, CPU_REG_RFLAGS);
|
||||||
error |= vm_get_register(vcpu, gpr, &val);
|
val = vm_get_register(vcpu, gpr);
|
||||||
vm_get_seg_desc(seg, &desc);
|
vm_get_seg_desc(seg, &desc);
|
||||||
|
|
||||||
if (error) {
|
|
||||||
pr_err("%s: error(%d) happens when getting cr0/rflags/segment"
|
|
||||||
"desc/gpr", __func__, error);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vie_calculate_gla(paging->cpu_mode, seg, &desc, val, opsize,
|
if (vie_calculate_gla(paging->cpu_mode, seg, &desc, val, opsize,
|
||||||
addrsize, prot, gla) != 0) {
|
addrsize, prot, gla) != 0) {
|
||||||
if (seg == CPU_REG_SS) {
|
if (seg == CPU_REG_SS) {
|
||||||
@ -1034,7 +1002,7 @@ static int emulate_movs(struct vcpu *vcpu, struct instr_emul_vie *vie,
|
|||||||
repeat = vie->repz_present | vie->repnz_present;
|
repeat = vie->repz_present | vie->repnz_present;
|
||||||
|
|
||||||
if (repeat != 0) {
|
if (repeat != 0) {
|
||||||
error = vm_get_register(vcpu, CPU_REG_RCX, &rcx);
|
rcx = vm_get_register(vcpu, CPU_REG_RCX);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The count register is %rcx, %ecx or %cx depending on the
|
* The count register is %rcx, %ecx or %cx depending on the
|
||||||
@ -1062,9 +1030,9 @@ static int emulate_movs(struct vcpu *vcpu, struct instr_emul_vie *vie,
|
|||||||
|
|
||||||
(void)memcpy_s((void *)dstaddr, 16U, (void *)srcaddr, opsize);
|
(void)memcpy_s((void *)dstaddr, 16U, (void *)srcaddr, opsize);
|
||||||
|
|
||||||
error = vm_get_register(vcpu, CPU_REG_RSI, &rsi);
|
rsi = vm_get_register(vcpu, CPU_REG_RSI);
|
||||||
error = vm_get_register(vcpu, CPU_REG_RDI, &rdi);
|
rdi = vm_get_register(vcpu, CPU_REG_RDI);
|
||||||
error = vm_get_register(vcpu, CPU_REG_RFLAGS, &rflags);
|
rflags = vm_get_register(vcpu, CPU_REG_RFLAGS);
|
||||||
|
|
||||||
if ((rflags & PSL_D) != 0U) {
|
if ((rflags & PSL_D) != 0U) {
|
||||||
rsi -= opsize;
|
rsi -= opsize;
|
||||||
@ -1107,7 +1075,7 @@ static int emulate_stos(struct vcpu *vcpu, struct instr_emul_vie *vie)
|
|||||||
repeat = vie->repz_present | vie->repnz_present;
|
repeat = vie->repz_present | vie->repnz_present;
|
||||||
|
|
||||||
if (repeat != 0) {
|
if (repeat != 0) {
|
||||||
error = vm_get_register(vcpu, CPU_REG_RCX, &rcx);
|
rcx = vm_get_register(vcpu, CPU_REG_RCX);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The count register is %rcx, %ecx or %cx depending on the
|
* The count register is %rcx, %ecx or %cx depending on the
|
||||||
@ -1118,15 +1086,15 @@ static int emulate_stos(struct vcpu *vcpu, struct instr_emul_vie *vie)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
error = vm_get_register(vcpu, CPU_REG_RAX, &val);
|
val = vm_get_register(vcpu, CPU_REG_RAX);
|
||||||
|
|
||||||
error = mmio_write(vcpu, val);
|
error = mmio_write(vcpu, val);
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = vm_get_register(vcpu, CPU_REG_RDI, &rdi);
|
rdi = vm_get_register(vcpu, CPU_REG_RDI);
|
||||||
error = vm_get_register(vcpu, CPU_REG_RFLAGS, &rflags);
|
rflags = vm_get_register(vcpu, CPU_REG_RFLAGS);
|
||||||
|
|
||||||
if ((rflags & PSL_D) != 0U) {
|
if ((rflags & PSL_D) != 0U) {
|
||||||
rdi -= opsize;
|
rdi -= opsize;
|
||||||
@ -1183,10 +1151,7 @@ static int emulate_test(struct vcpu *vcpu, struct instr_emul_vie *vie)
|
|||||||
|
|
||||||
/* get the first operand */
|
/* get the first operand */
|
||||||
reg = vie->reg;
|
reg = vie->reg;
|
||||||
error = vm_get_register(vcpu, reg, &val1);
|
val1 = vm_get_register(vcpu, reg);
|
||||||
if (error != 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get the second operand */
|
/* get the second operand */
|
||||||
error = mmio_read(vcpu, &val2);
|
error = mmio_read(vcpu, &val2);
|
||||||
@ -1239,10 +1204,7 @@ static int emulate_and(struct vcpu *vcpu, struct instr_emul_vie *vie)
|
|||||||
|
|
||||||
/* get the first operand */
|
/* get the first operand */
|
||||||
reg = vie->reg;
|
reg = vie->reg;
|
||||||
error = vm_get_register(vcpu, reg, &val1);
|
val1 = vm_get_register(vcpu, reg);
|
||||||
if (error != 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get the second operand */
|
/* get the second operand */
|
||||||
error = mmio_read(vcpu, &val2);
|
error = mmio_read(vcpu, &val2);
|
||||||
@ -1361,10 +1323,7 @@ static int emulate_or(struct vcpu *vcpu, struct instr_emul_vie *vie)
|
|||||||
|
|
||||||
/* get the second operand */
|
/* get the second operand */
|
||||||
reg = vie->reg;
|
reg = vie->reg;
|
||||||
error = vm_get_register(vcpu, reg, &val2);
|
val2 = vm_get_register(vcpu, reg);
|
||||||
if (error != 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* perform the operation and write the result */
|
/* perform the operation and write the result */
|
||||||
result = val1 | val2;
|
result = val1 | val2;
|
||||||
@ -1419,10 +1378,7 @@ static int emulate_cmp(struct vcpu *vcpu, struct instr_emul_vie *vie)
|
|||||||
|
|
||||||
/* Get the register operand */
|
/* Get the register operand */
|
||||||
reg = vie->reg;
|
reg = vie->reg;
|
||||||
error = vm_get_register(vcpu, reg, ®op);
|
regop = vm_get_register(vcpu, reg);
|
||||||
if (error != 0) {
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the memory operand */
|
/* Get the memory operand */
|
||||||
error = mmio_read(vcpu, &memop);
|
error = mmio_read(vcpu, &memop);
|
||||||
@ -1508,10 +1464,7 @@ static int emulate_sub(struct vcpu *vcpu, struct instr_emul_vie *vie)
|
|||||||
|
|
||||||
/* get the first operand */
|
/* get the first operand */
|
||||||
reg = vie->reg;
|
reg = vie->reg;
|
||||||
error = vm_get_register(vcpu, reg, &val1);
|
val1 = vm_get_register(vcpu, reg);
|
||||||
if (error != 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get the second operand */
|
/* get the second operand */
|
||||||
error = mmio_read(vcpu, &val2);
|
error = mmio_read(vcpu, &val2);
|
||||||
@ -1582,9 +1535,9 @@ static int emulate_stack_op(struct vcpu *vcpu, struct instr_emul_vie *vie,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
error = vm_get_register(vcpu, CPU_REG_CR0, &cr0);
|
cr0 = vm_get_register(vcpu, CPU_REG_CR0);
|
||||||
error = vm_get_register(vcpu, CPU_REG_RFLAGS, &rflags);
|
rflags = vm_get_register(vcpu, CPU_REG_RFLAGS);
|
||||||
error = vm_get_register(vcpu, CPU_REG_RSP, &rsp);
|
rsp = vm_get_register(vcpu, CPU_REG_RSP);
|
||||||
|
|
||||||
if (pushop != 0) {
|
if (pushop != 0) {
|
||||||
rsp -= size;
|
rsp -= size;
|
||||||
@ -1711,7 +1664,7 @@ static int emulate_bittest(struct vcpu *vcpu, struct instr_emul_vie *vie)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = vm_get_register(vcpu, CPU_REG_RFLAGS, &rflags);
|
rflags = vm_get_register(vcpu, CPU_REG_RFLAGS);
|
||||||
|
|
||||||
error = mmio_read(vcpu, &val);
|
error = mmio_read(vcpu, &val);
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
|
Loading…
Reference in New Issue
Block a user