mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-22 21:47:22 +00:00
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:
parent
1d98b7012d
commit
55e5ed2e1a
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user