HV: instr_emul: Add new function vie_update_rflags

There are some duplicate codes in emulate_xxx functions which update rflags and
it deserves a common function to deal with the situation. So, this patch
introduces a new function vie_update_rflags to updating rflags accordingly.

Signed-off-by: Kaige Fu <kaige.fu@intel.com>
Acked-by: Anthony Xu <anthony.xu@intel.com>
This commit is contained in:
Kaige Fu 2018-07-12 15:32:17 +08:00 committed by lijinxia
parent 2f3eb6723d
commit 44a175e4fe

View File

@ -361,6 +361,26 @@ vie_update_register(struct vcpu *vcpu, enum cpu_reg_name reg,
#define RFLAGS_STATUS_BITS (PSL_C | PSL_PF | PSL_AF | PSL_Z | PSL_N | PSL_V)
static int vie_update_rflags(struct vcpu *vcpu, uint64_t rflags2, uint64_t psl)
{
int error;
uint8_t size;
uint64_t rflags;
error = vie_read_register(vcpu, CPU_REG_RFLAGS, &rflags);
if (error != 0) {
return error;
}
rflags &= ~RFLAGS_STATUS_BITS;
rflags |= rflags2 & psl;
size = 8U;
error = vie_update_register(vcpu, CPU_REG_RFLAGS, rflags, size);
return error;
}
/*
* Return the status flags that would result from doing (x - y).
*/
@ -832,7 +852,7 @@ emulate_test(struct vcpu *vcpu, uint64_t gpa, struct vie *vie,
int error;
uint8_t size;
enum cpu_reg_name reg;
uint64_t result, rflags, rflags2, val1, val2;
uint64_t result, rflags2, val1, val2;
size = vie->opsize;
error = -EINVAL;
@ -878,11 +898,6 @@ emulate_test(struct vcpu *vcpu, uint64_t gpa, struct vie *vie,
return error;
}
error = vie_read_register(vcpu, CPU_REG_RFLAGS, &rflags);
if (error != 0) {
return error;
}
/*
* OF and CF are cleared; the SF, ZF and PF flags are set according
* to the result; AF is undefined.
@ -890,10 +905,8 @@ emulate_test(struct vcpu *vcpu, uint64_t gpa, struct vie *vie,
* The updated status flags are obtained by subtracting 0 from 'result'.
*/
rflags2 = getcc(size, result, 0UL);
rflags &= ~RFLAGS_STATUS_BITS;
rflags |= rflags2 & (PSL_PF | PSL_Z | PSL_N);
size = 8U;
error = vie_update_register(vcpu, CPU_REG_RFLAGS, rflags, size);
error = vie_update_rflags(vcpu, rflags2, PSL_PF | PSL_Z | PSL_N);
return error;
}
@ -905,7 +918,7 @@ emulate_and(struct vcpu *vcpu, uint64_t gpa, struct vie *vie,
int error;
uint8_t size;
enum cpu_reg_name reg;
uint64_t result, rflags, rflags2, val1, val2;
uint64_t result, rflags2, val1, val2;
size = vie->opsize;
error = -EINVAL;
@ -974,11 +987,6 @@ emulate_and(struct vcpu *vcpu, uint64_t gpa, struct vie *vie,
return error;
}
error = vie_read_register(vcpu, CPU_REG_RFLAGS, &rflags);
if (error != 0) {
return error;
}
/*
* OF and CF are cleared; the SF, ZF and PF flags are set according
* to the result; AF is undefined.
@ -986,10 +994,8 @@ emulate_and(struct vcpu *vcpu, uint64_t gpa, struct vie *vie,
* The updated status flags are obtained by subtracting 0 from 'result'.
*/
rflags2 = getcc(size, result, 0UL);
rflags &= ~RFLAGS_STATUS_BITS;
rflags |= rflags2 & (PSL_PF | PSL_Z | PSL_N);
size = 8U;
error = vie_update_register(vcpu, CPU_REG_RFLAGS, rflags, size);
error = vie_update_rflags(vcpu, rflags2, PSL_PF | PSL_Z | PSL_N);
return error;
}
@ -1001,7 +1007,7 @@ emulate_or(struct vcpu *vcpu, uint64_t gpa, struct vie *vie,
int error;
uint8_t size;
enum cpu_reg_name reg;
uint64_t val1, val2, result, rflags, rflags2;
uint64_t val1, val2, result, rflags2;
size = vie->opsize;
error = -EINVAL;
@ -1073,11 +1079,6 @@ emulate_or(struct vcpu *vcpu, uint64_t gpa, struct vie *vie,
return error;
}
error = vie_read_register(vcpu, CPU_REG_RFLAGS, &rflags);
if (error != 0) {
return error;
}
/*
* OF and CF are cleared; the SF, ZF and PF flags are set according
* to the result; AF is undefined.
@ -1085,10 +1086,8 @@ emulate_or(struct vcpu *vcpu, uint64_t gpa, struct vie *vie,
* The updated status flags are obtained by subtracting 0 from 'result'.
*/
rflags2 = getcc(size, result, 0UL);
rflags &= ~RFLAGS_STATUS_BITS;
rflags |= rflags2 & (PSL_PF | PSL_Z | PSL_N);
size = 8U;
error = vie_update_register(vcpu, CPU_REG_RFLAGS, rflags, size);
error = vie_update_rflags(vcpu, rflags2, PSL_PF | PSL_Z | PSL_N);
return error;
}
@ -1099,7 +1098,7 @@ emulate_cmp(struct vcpu *vcpu, uint64_t gpa, struct vie *vie,
{
int error;
uint8_t size;
uint64_t regop, memop, op1, op2, rflags, rflags2;
uint64_t regop, memop, op1, op2, rflags2;
enum cpu_reg_name reg;
size = vie->opsize;
@ -1184,14 +1183,9 @@ emulate_cmp(struct vcpu *vcpu, uint64_t gpa, struct vie *vie,
default:
return -EINVAL;
}
error = vie_read_register(vcpu, CPU_REG_RFLAGS, &rflags);
if (error != 0) {
return error;
}
rflags &= ~RFLAGS_STATUS_BITS;
rflags |= rflags2 & RFLAGS_STATUS_BITS;
size = 8U;
error = vie_update_register(vcpu, CPU_REG_RFLAGS, rflags, size);
error = vie_update_rflags(vcpu, rflags2, RFLAGS_STATUS_BITS);
return error;
}
@ -1202,7 +1196,7 @@ emulate_sub(struct vcpu *vcpu, uint64_t gpa, struct vie *vie,
{
int error;
uint8_t size;
uint64_t nval, rflags, rflags2, val1, val2;
uint64_t nval, rflags2, val1, val2;
enum cpu_reg_name reg;
size = vie->opsize;
@ -1240,21 +1234,13 @@ emulate_sub(struct vcpu *vcpu, uint64_t gpa, struct vie *vie,
break;
}
if (error == 0) {
rflags2 = getcc(size, val1, val2);
error = vie_read_register(vcpu, CPU_REG_RFLAGS,
&rflags);
if (error != 0) {
return error;
}
rflags &= ~RFLAGS_STATUS_BITS;
rflags |= rflags2 & RFLAGS_STATUS_BITS;
size = 8U;
error = vie_update_register(vcpu, CPU_REG_RFLAGS,
rflags, size);
if (error != 0) {
return error;
}
rflags2 = getcc(size, val1, val2);
error = vie_update_rflags(vcpu, rflags2, RFLAGS_STATUS_BITS);
return error;
}