diff --git a/hypervisor/arch/x86/io.c b/hypervisor/arch/x86/io.c index 6817ea6c1..af1b963fe 100644 --- a/hypervisor/arch/x86/io.c +++ b/hypervisor/arch/x86/io.c @@ -152,7 +152,11 @@ void emulate_io_post(struct acrn_vcpu *vcpu) switch (vcpu->req.type) { case REQ_MMIO: - request_vcpu_pre_work(vcpu, ACRN_VCPU_MMIO_COMPLETE); + if (!vcpu->vm->sw.is_completion_polling) { + request_vcpu_pre_work(vcpu, ACRN_VCPU_MMIO_COMPLETE); + } else { + dm_emulate_mmio_post(vcpu); + } break; case REQ_PORTIO: @@ -173,7 +177,10 @@ void emulate_io_post(struct acrn_vcpu *vcpu) break; } - resume_vcpu(vcpu); + if (!vcpu->vm->sw.is_completion_polling) { + resume_vcpu(vcpu); + } + } /** diff --git a/hypervisor/common/io_request.c b/hypervisor/common/io_request.c index ace9a0873..57daddaf8 100644 --- a/hypervisor/common/io_request.c +++ b/hypervisor/common/io_request.c @@ -78,29 +78,6 @@ static inline bool has_complete_ioreq(struct acrn_vcpu *vcpu) return (get_vhm_req_state(vcpu->vm, vcpu->vcpu_id) == REQ_STATE_COMPLETE); } -/** - * @brief Handle completed ioreq if any one pending - * - * @param pcpu_id The physical cpu id of vcpu whose IO request to be checked - * - * @return None - */ -void handle_complete_ioreq(uint16_t pcpu_id) -{ - struct acrn_vcpu *vcpu = get_ever_run_vcpu(pcpu_id); - struct acrn_vm *vm; - - if (vcpu != NULL) { - vm = vcpu->vm; - if (vm->sw.is_completion_polling) { - if (has_complete_ioreq(vcpu)) { - /* we have completed ioreq pending */ - emulate_io_post(vcpu); - } - } - } -} - /** * @brief Deliver \p io_req to SOS and suspend \p vcpu till its completion * @@ -113,6 +90,7 @@ int32_t acrn_insert_request_wait(struct acrn_vcpu *vcpu, const struct io_request { union vhm_request_buffer *req_buf = NULL; struct vhm_request *vhm_req; + bool is_polling = false; uint16_t cur; if (vcpu->vm->sw.io_shared_page == NULL) { @@ -133,14 +111,17 @@ int32_t acrn_insert_request_wait(struct acrn_vcpu *vcpu, const struct io_request &io_req->reqs, sizeof(union vhm_io_request)); if (vcpu->vm->sw.is_completion_polling) { vhm_req->completion_polling = 1U; + is_polling = true; } clac(); - /* pause vcpu, wait for VHM to handle the MMIO request. + /* pause vcpu in notification mode , wait for VHM to handle the MMIO request. * TODO: when pause_vcpu changed to switch vcpu out directlly, we * should fix the race issue between req.processed update and vcpu pause */ - pause_vcpu(vcpu, VCPU_PAUSED); + if (!is_polling) { + pause_vcpu(vcpu, VCPU_PAUSED); + } /* Must clear the signal before we mark req as pending * Once we mark it pending, VHM may process req and signal us @@ -158,6 +139,24 @@ int32_t acrn_insert_request_wait(struct acrn_vcpu *vcpu, const struct io_request /* signal VHM */ fire_vhm_interrupt(); + /* Polling completion of the request in polling mode */ + if (is_polling) { + /* + * Now, we only have one case that will schedule out this vcpu + * from IO completion polling status, it's pause_vcpu to VCPU_ZOMBIE. + * In this case, we cannot come back to polling status again. Currently, + * it's OK as we needn't handle IO completion in zombie status. + */ + while (!need_reschedule(vcpu->pcpu_id)) { + if (has_complete_ioreq(vcpu)) { + /* we have completed ioreq pending */ + emulate_io_post(vcpu); + break; + } + __asm __volatile("pause" ::: "memory"); + } + } + return 0; } diff --git a/hypervisor/common/schedule.c b/hypervisor/common/schedule.c index 4d749801b..570e357a9 100644 --- a/hypervisor/common/schedule.c +++ b/hypervisor/common/schedule.c @@ -178,7 +178,6 @@ void default_idle(void) cpu_dead(); } else { CPU_IRQ_ENABLE(); - handle_complete_ioreq(pcpu_id); cpu_do_idle(); CPU_IRQ_DISABLE(); } diff --git a/hypervisor/include/arch/x86/ioreq.h b/hypervisor/include/arch/x86/ioreq.h index 8798de92a..b25b1ad83 100644 --- a/hypervisor/include/arch/x86/ioreq.h +++ b/hypervisor/include/arch/x86/ioreq.h @@ -296,15 +296,6 @@ int32_t acrn_insert_request_wait(struct acrn_vcpu *vcpu, const struct io_request */ void reset_vm_ioreqs(struct acrn_vm *vm); -/** - * @brief Handle completed ioreq if any one pending - * - * @param pcpu_id The physical cpu id of vcpu whose IO request to be checked - * - * @return None - */ -void handle_complete_ioreq(uint16_t pcpu_id); - /** * @brief Get the state of VHM request *