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) #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). * 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; int error;
uint8_t size; uint8_t size;
enum cpu_reg_name reg; enum cpu_reg_name reg;
uint64_t result, rflags, rflags2, val1, val2; uint64_t result, rflags2, val1, val2;
size = vie->opsize; size = vie->opsize;
error = -EINVAL; error = -EINVAL;
@ -878,11 +898,6 @@ emulate_test(struct vcpu *vcpu, uint64_t gpa, struct vie *vie,
return error; 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 * OF and CF are cleared; the SF, ZF and PF flags are set according
* to the result; AF is undefined. * 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'. * The updated status flags are obtained by subtracting 0 from 'result'.
*/ */
rflags2 = getcc(size, result, 0UL); rflags2 = getcc(size, result, 0UL);
rflags &= ~RFLAGS_STATUS_BITS; error = vie_update_rflags(vcpu, rflags2, PSL_PF | PSL_Z | PSL_N);
rflags |= rflags2 & (PSL_PF | PSL_Z | PSL_N);
size = 8U;
error = vie_update_register(vcpu, CPU_REG_RFLAGS, rflags, size);
return error; return error;
} }
@ -905,7 +918,7 @@ emulate_and(struct vcpu *vcpu, uint64_t gpa, struct vie *vie,
int error; int error;
uint8_t size; uint8_t size;
enum cpu_reg_name reg; enum cpu_reg_name reg;
uint64_t result, rflags, rflags2, val1, val2; uint64_t result, rflags2, val1, val2;
size = vie->opsize; size = vie->opsize;
error = -EINVAL; error = -EINVAL;
@ -974,11 +987,6 @@ emulate_and(struct vcpu *vcpu, uint64_t gpa, struct vie *vie,
return error; 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 * OF and CF are cleared; the SF, ZF and PF flags are set according
* to the result; AF is undefined. * 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'. * The updated status flags are obtained by subtracting 0 from 'result'.
*/ */
rflags2 = getcc(size, result, 0UL); rflags2 = getcc(size, result, 0UL);
rflags &= ~RFLAGS_STATUS_BITS; error = vie_update_rflags(vcpu, rflags2, PSL_PF | PSL_Z | PSL_N);
rflags |= rflags2 & (PSL_PF | PSL_Z | PSL_N);
size = 8U;
error = vie_update_register(vcpu, CPU_REG_RFLAGS, rflags, size);
return error; return error;
} }
@ -1001,7 +1007,7 @@ emulate_or(struct vcpu *vcpu, uint64_t gpa, struct vie *vie,
int error; int error;
uint8_t size; uint8_t size;
enum cpu_reg_name reg; enum cpu_reg_name reg;
uint64_t val1, val2, result, rflags, rflags2; uint64_t val1, val2, result, rflags2;
size = vie->opsize; size = vie->opsize;
error = -EINVAL; error = -EINVAL;
@ -1073,11 +1079,6 @@ emulate_or(struct vcpu *vcpu, uint64_t gpa, struct vie *vie,
return error; 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 * OF and CF are cleared; the SF, ZF and PF flags are set according
* to the result; AF is undefined. * 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'. * The updated status flags are obtained by subtracting 0 from 'result'.
*/ */
rflags2 = getcc(size, result, 0UL); rflags2 = getcc(size, result, 0UL);
rflags &= ~RFLAGS_STATUS_BITS; error = vie_update_rflags(vcpu, rflags2, PSL_PF | PSL_Z | PSL_N);
rflags |= rflags2 & (PSL_PF | PSL_Z | PSL_N);
size = 8U;
error = vie_update_register(vcpu, CPU_REG_RFLAGS, rflags, size);
return error; return error;
} }
@ -1099,7 +1098,7 @@ emulate_cmp(struct vcpu *vcpu, uint64_t gpa, struct vie *vie,
{ {
int error; int error;
uint8_t size; uint8_t size;
uint64_t regop, memop, op1, op2, rflags, rflags2; uint64_t regop, memop, op1, op2, rflags2;
enum cpu_reg_name reg; enum cpu_reg_name reg;
size = vie->opsize; size = vie->opsize;
@ -1184,14 +1183,9 @@ emulate_cmp(struct vcpu *vcpu, uint64_t gpa, struct vie *vie,
default: default:
return -EINVAL; return -EINVAL;
} }
error = vie_read_register(vcpu, CPU_REG_RFLAGS, &rflags);
if (error != 0) { error = vie_update_rflags(vcpu, rflags2, RFLAGS_STATUS_BITS);
return error;
}
rflags &= ~RFLAGS_STATUS_BITS;
rflags |= rflags2 & RFLAGS_STATUS_BITS;
size = 8U;
error = vie_update_register(vcpu, CPU_REG_RFLAGS, rflags, size);
return error; return error;
} }
@ -1202,7 +1196,7 @@ emulate_sub(struct vcpu *vcpu, uint64_t gpa, struct vie *vie,
{ {
int error; int error;
uint8_t size; uint8_t size;
uint64_t nval, rflags, rflags2, val1, val2; uint64_t nval, rflags2, val1, val2;
enum cpu_reg_name reg; enum cpu_reg_name reg;
size = vie->opsize; size = vie->opsize;
@ -1240,20 +1234,12 @@ emulate_sub(struct vcpu *vcpu, uint64_t gpa, struct vie *vie,
break; break;
} }
if (error == 0) {
rflags2 = getcc(size, val1, val2);
error = vie_read_register(vcpu, CPU_REG_RFLAGS,
&rflags);
if (error != 0) { if (error != 0) {
return error; return error;
} }
rflags &= ~RFLAGS_STATUS_BITS; rflags2 = getcc(size, val1, val2);
rflags |= rflags2 & RFLAGS_STATUS_BITS; error = vie_update_rflags(vcpu, rflags2, RFLAGS_STATUS_BITS);
size = 8U;
error = vie_update_register(vcpu, CPU_REG_RFLAGS,
rflags, size);
}
return error; return error;
} }