hv: remove unnecessary check for gva

According to SDM vol3 25.1.1
With VMX enabled, following exception will be handled by guest
without trigger VM exit:
 - faults based on privilege level
 - general protection due to relevent segment being unusable
 - general protection due to offset beyond limit of relevent segment
 - alignment check exception

ACRN always assume VMX is enabled. So we don't need to these check
in instruction emulation. But we need to do page fault related check.

Signed-off-by: Yin Fengwei <fengwei.yin@intel.com>
Acked-by: Anthony Xu <anthony.xu@intel.com>
This commit is contained in:
Yin Fengwei 2018-08-13 15:53:54 +08:00 committed by lijinxia
parent 5663dd7d14
commit 54c254169d
1 changed files with 7 additions and 72 deletions

View File

@ -385,18 +385,6 @@ static void get_guest_paging_info(struct vcpu *vcpu, struct instr_emul_ctxt *emu
emul_ctxt->paging.paging_mode = get_vcpu_paging_mode(vcpu);
}
static int vie_alignment_check(uint8_t cpl, uint8_t size, uint64_t cr0,
uint64_t rflags, uint64_t gla)
{
pr_dbg("Checking alignment with cpl: %hhu, addrsize: %hhu", cpl, size);
if (cpl < 3U || (cr0 & CR0_AM) == 0UL || (rflags & PSL_AC) == 0UL) {
return 0;
}
return ((gla & (size - 1U)) != 0UL) ? 1 : 0;
}
static int vie_canonical_check(enum vm_cpu_mode cpu_mode, uint64_t gla)
{
uint64_t mask;
@ -426,12 +414,11 @@ static int vie_canonical_check(enum vm_cpu_mode cpu_mode, uint64_t gla)
*return -1 - on failure
*/
static int vie_calculate_gla(enum vm_cpu_mode cpu_mode, enum cpu_reg_name seg,
struct seg_desc *desc, uint64_t offset_arg, uint8_t length_arg,
uint8_t addrsize, uint32_t prot, uint64_t *gla)
struct seg_desc *desc, uint64_t offset_arg, uint8_t addrsize,
uint32_t prot, uint64_t *gla)
{
uint64_t firstoff, low_limit, high_limit, segbase;
uint64_t firstoff, segbase;
uint64_t offset = offset_arg;
uint8_t length = length_arg;
uint8_t glasize;
uint32_t type;
@ -450,25 +437,6 @@ static int vie_calculate_gla(enum vm_cpu_mode cpu_mode, enum cpu_reg_name seg,
return -1;
}
glasize = 4U;
/*
* If the segment selector is loaded with a NULL selector
* then the descriptor is unusable and attempting to use
* it results in a #GP(0).
*/
if (SEG_DESC_UNUSABLE(desc->access)) {
return -1;
}
/*
* The processor generates a #NP exception when a segment
* register is loaded with a selector that points to a
* descriptor that is not present. If this was the case then
* it would have been checked before the VM-exit.
*/
if (SEG_DESC_PRESENT(desc->access) != 0) {
/* TODO: Inject #NP */
return -1;
}
/* The descriptor type must indicate a code/data segment. */
type = SEG_DESC_TYPE(desc->access);
@ -497,30 +465,6 @@ static int vie_calculate_gla(enum vm_cpu_mode cpu_mode, enum cpu_reg_name seg,
return -1;
}
}
/*
* 'desc->limit' is fully expanded taking granularity into
* account.
*/
if ((type & 0xCU) == 0x4U) {
/* expand-down data segment */
low_limit = desc->limit + 1U;
high_limit = SEG_DESC_DEF32(desc->access) ?
0xffffffffU : 0xffffU;
} else {
/* code segment or expand-up data segment */
low_limit = 0U;
high_limit = desc->limit;
}
while (length > 0U) {
offset &= size2mask[addrsize];
if (offset < low_limit || offset > high_limit) {
return -1;
}
offset++;
length--;
}
}
/*
@ -932,6 +876,7 @@ static int get_gla(struct vcpu *vcpu, __unused struct instr_emul_vie *vie,
uint8_t opsize, uint8_t addrsize, uint32_t prot, enum cpu_reg_name seg,
enum cpu_reg_name gpr, uint64_t *gla, int *fault)
{
int ret;
struct seg_desc desc;
uint64_t cr0, val, rflags;
@ -940,13 +885,11 @@ static int get_gla(struct vcpu *vcpu, __unused struct instr_emul_vie *vie,
val = vm_get_register(vcpu, gpr);
vm_get_seg_desc(seg, &desc);
if (vie_calculate_gla(paging->cpu_mode, seg, &desc, val, opsize,
if (vie_calculate_gla(paging->cpu_mode, seg, &desc, val,
addrsize, prot, gla) != 0) {
if (seg == CPU_REG_SS) {
/*vm_inject_ss(vcpu, 0);*/
pr_err("TODO: inject ss exception");
} else {
/*vm_inject_gp(vcpu);*/
pr_err("TODO: inject gp exception");
}
goto guest_fault;
@ -954,27 +897,19 @@ static int get_gla(struct vcpu *vcpu, __unused struct instr_emul_vie *vie,
if (vie_canonical_check(paging->cpu_mode, *gla) != 0) {
if (seg == CPU_REG_SS) {
/*vm_inject_ss(vcpu, 0);*/
pr_err("TODO: inject ss exception");
} else {
/*vm_inject_gp(vcpu);*/
pr_err("TODO: inject gp exception");
}
goto guest_fault;
}
if (vie_alignment_check(paging->cpl, opsize, cr0, rflags, *gla) != 0) {
/*vm_inject_ac(vcpu, 0);*/
pr_err("TODO: inject ac exception");
goto guest_fault;
}
*fault = 0;
return 0;
guest_fault:
*fault = 1;
return 0;
return ret;
}
static int emulate_movs(struct vcpu *vcpu, struct instr_emul_vie *vie,