hv:move ept violation handler to io_emul.c

move this api from ept.c to io_emul.c to avoid
reverse dependency.

Tracked-On: #1842
Signed-off-by: Mingqiang Chi <mingqiang.chi@intel.com>
Reviewed-by: Jason Chen CJ <jason.cj.chen@intel.com>
Reviewed-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Mingqiang Chi 2019-01-18 14:04:09 +08:00 committed by wenlingz
parent 1d98b7012d
commit 55e5ed2e1a
6 changed files with 95 additions and 94 deletions

View File

@ -341,3 +341,6 @@ The following APIs are provided for I/O emulation at runtime:
.. doxygenfunction:: pio_instr_vmexit_handler
:project: Project ACRN
.. doxygenfunction:: ept_violation_vmexit_handler
:project: Project ACRN

View File

@ -460,9 +460,6 @@ EPT
.. doxygenfunction:: invept
:project: Project ACRN
.. doxygenfunction:: ept_violation_vmexit_handler
:project: Project ACRN
.. doxygenfunction:: ept_misconfig_vmexit_handler
:project: Project ACRN

View File

@ -72,88 +72,6 @@ uint64_t vm0_hpa2gpa(uint64_t hpa)
return hpa;
}
int32_t ept_violation_vmexit_handler(struct acrn_vcpu *vcpu)
{
int32_t status = -EINVAL, ret;
uint64_t exit_qual;
uint64_t gpa;
struct io_request *io_req = &vcpu->req;
struct mmio_request *mmio_req = &io_req->reqs.mmio;
/* Handle page fault from guest */
exit_qual = vcpu->arch.exit_qualification;
io_req->type = REQ_MMIO;
/* Specify if read or write operation */
if ((exit_qual & 0x2UL) != 0UL) {
/* Write operation */
mmio_req->direction = REQUEST_WRITE;
mmio_req->value = 0UL;
/* XXX: write access while EPT perm RX -> WP */
if ((exit_qual & 0x38UL) == 0x28UL) {
io_req->type = REQ_WP;
}
} else {
/* Read operation */
mmio_req->direction = REQUEST_READ;
/* TODO: Need to determine how sign extension is determined for
* reads
*/
}
/* Get the guest physical address */
gpa = exec_vmread64(VMX_GUEST_PHYSICAL_ADDR_FULL);
TRACE_2L(TRACE_VMEXIT_EPT_VIOLATION, exit_qual, gpa);
/* Adjust IPA appropriately and OR page offset to get full IPA of abort
*/
mmio_req->address = gpa;
ret = decode_instruction(vcpu);
if (ret > 0) {
mmio_req->size = (uint64_t)ret;
/*
* For MMIO write, ask DM to run MMIO emulation after
* instruction emulation. For MMIO read, ask DM to run MMIO
* emulation at first.
*/
/* Determine value being written. */
if (mmio_req->direction == REQUEST_WRITE) {
status = emulate_instruction(vcpu);
if (status != 0) {
ret = -EFAULT;
}
}
if (ret > 0) {
status = emulate_io(vcpu, io_req);
if (status == 0) {
emulate_mmio_post(vcpu, io_req);
} else {
if (status == IOREQ_PENDING) {
status = 0;
}
}
}
} else {
if (ret == -EFAULT) {
pr_info("page fault happen during decode_instruction");
status = 0;
}
}
if (ret <= 0) {
pr_acrnlog("Guest Linear Address: 0x%016llx", exec_vmread(VMX_GUEST_LINEAR_ADDR));
pr_acrnlog("Guest Physical Address address: 0x%016llx", gpa);
}
return status;
}
int32_t ept_misconfig_vmexit_handler(__unused struct acrn_vcpu *vcpu)
{
int32_t status;

View File

@ -403,6 +403,87 @@ int32_t pio_instr_vmexit_handler(struct acrn_vcpu *vcpu)
return status;
}
int32_t ept_violation_vmexit_handler(struct acrn_vcpu *vcpu)
{
int32_t status = -EINVAL, ret;
uint64_t exit_qual;
uint64_t gpa;
struct io_request *io_req = &vcpu->req;
struct mmio_request *mmio_req = &io_req->reqs.mmio;
/* Handle page fault from guest */
exit_qual = vcpu->arch.exit_qualification;
io_req->type = REQ_MMIO;
/* Specify if read or write operation */
if ((exit_qual & 0x2UL) != 0UL) {
/* Write operation */
mmio_req->direction = REQUEST_WRITE;
mmio_req->value = 0UL;
/* XXX: write access while EPT perm RX -> WP */
if ((exit_qual & 0x38UL) == 0x28UL) {
io_req->type = REQ_WP;
}
} else {
/* Read operation */
mmio_req->direction = REQUEST_READ;
/* TODO: Need to determine how sign extension is determined for
* reads
*/
}
/* Get the guest physical address */
gpa = exec_vmread64(VMX_GUEST_PHYSICAL_ADDR_FULL);
TRACE_2L(TRACE_VMEXIT_EPT_VIOLATION, exit_qual, gpa);
/* Adjust IPA appropriately and OR page offset to get full IPA of abort
*/
mmio_req->address = gpa;
ret = decode_instruction(vcpu);
if (ret > 0) {
mmio_req->size = (uint64_t)ret;
/*
* For MMIO write, ask DM to run MMIO emulation after
* instruction emulation. For MMIO read, ask DM to run MMIO
* emulation at first.
*/
/* Determine value being written. */
if (mmio_req->direction == REQUEST_WRITE) {
status = emulate_instruction(vcpu);
if (status != 0) {
ret = -EFAULT;
}
}
if (ret > 0) {
status = emulate_io(vcpu, io_req);
if (status == 0) {
emulate_mmio_post(vcpu, io_req);
} else {
if (status == IOREQ_PENDING) {
status = 0;
}
}
}
} else {
if (ret == -EFAULT) {
pr_info("page fault happen during decode_instruction");
status = 0;
}
}
if (ret <= 0) {
pr_acrnlog("Guest Linear Address: 0x%016llx", exec_vmread(VMX_GUEST_LINEAR_ADDR));
pr_acrnlog("Guest Physical Address address: 0x%016llx", gpa);
}
return status;
}
/**
* @brief Allow a VM to access a port I/O range

View File

@ -79,6 +79,16 @@ int32_t emulate_io(struct acrn_vcpu *vcpu, struct io_request *io_req);
*/
int32_t pio_instr_vmexit_handler(struct acrn_vcpu *vcpu);
/**
* @brief EPT violation handling
*
* @param[in] vcpu the pointer that points to vcpu data structure
*
* @retval -EINVAL fail to handle the EPT violation
* @retval 0 Success to handle the EPT violation
*/
int32_t ept_violation_vmexit_handler(struct acrn_vcpu *vcpu);
/**
* @brief Allow a VM to access a port I/O range
*

View File

@ -294,15 +294,7 @@ void ept_mr_modify(struct acrn_vm *vm, uint64_t *pml4_page, uint64_t gpa,
*/
void ept_mr_del(struct acrn_vm *vm, uint64_t *pml4_page, uint64_t gpa,
uint64_t size);
/**
* @brief EPT violation handling
*
* @param[in] vcpu the pointer that points to vcpu data structure
*
* @retval -EINVAL fail to handle the EPT violation
* @retval 0 Success to handle the EPT violation
*/
int32_t ept_violation_vmexit_handler(struct acrn_vcpu *vcpu);
/**
* @brief EPT misconfiguration handling
*