HV: io: refine state transitions of VHM requests

Instead of using two members for maintaining the state of a VHM request, this
patch replaces the transitions with a single state. Basically the lifecycle of a
VHM request shall be:

    FREE -> PENDING -> PROCESSING -> COMPLETE -> FREE -> ...

The structure header of vhm_request has more details of the transitions access
limitations under different states.

Also drop the set but unused member vcpu.ioreq_pending.

For backward-compatibility, the obsolete 'valid' member is still kept and
maintained before SOS and DM adapts to the new state transitions.

v2 -> v3:

    * Use complete_ioreq to mark an I/O request finished in
      dm_emulate_(pio|mmio)_post.

Signed-off-by: Junjie Mao <junjie.mao@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Junjie Mao
2018-07-27 21:24:39 +08:00
committed by lijinxia
parent 941eb9db02
commit 17771c0ac2
8 changed files with 144 additions and 51 deletions

View File

@@ -334,6 +334,8 @@ int32_t hcall_set_ioreq_buffer(struct vm *vm, uint16_t vmid, uint64_t param)
uint64_t hpa = 0UL;
struct acrn_set_ioreq_buffer iobuf;
struct vm *target_vm = get_vm_from_vmid(vmid);
union vhm_request_buffer *req_buf;
uint16_t i;
if (target_vm == NULL) {
return -1;
@@ -358,6 +360,11 @@ int32_t hcall_set_ioreq_buffer(struct vm *vm, uint16_t vmid, uint64_t param)
target_vm->sw.io_shared_page = HPA2HVA(hpa);
req_buf = target_vm->sw.io_shared_page;
for (i = 0U; i < VHM_REQUEST_MAX; i++) {
atomic_store32(&req_buf->req_queue[i].processed, REQ_STATE_FREE);
}
return ret;
}

View File

@@ -72,12 +72,14 @@ acrn_insert_request_wait(struct vcpu *vcpu, struct io_request *io_req)
}
req_buf = (union vhm_request_buffer *)(vcpu->vm->sw.io_shared_page);
/* ACRN insert request to VHM and inject upcall */
cur = vcpu->vcpu_id;
vhm_req = &req_buf->req_queue[cur];
ASSERT(atomic_load32(&vhm_req->processed) == REQ_STATE_FREE,
"VHM request buffer is busy");
/* ACRN insert request to VHM and inject upcall */
vhm_req->type = io_req->type;
vhm_req->processed = io_req->processed;
(void)memcpy_s(&vhm_req->reqs, sizeof(union vhm_io_request),
&io_req->reqs, sizeof(union vhm_io_request));
@@ -85,15 +87,15 @@ acrn_insert_request_wait(struct vcpu *vcpu, struct io_request *io_req)
* TODO: when pause_vcpu changed to switch vcpu out directlly, we
* should fix the race issue between req.valid = true and vcpu pause
*/
atomic_store32(&vcpu->ioreq_pending, 1U);
pause_vcpu(vcpu, VCPU_PAUSED);
/* Must clear the signal before we mark req valid
* Once we mark to valid, VHM may process req and signal us
/* Must clear the signal before we mark req as pending
* Once we mark it pending, VHM may process req and signal us
* before we perform upcall.
* because VHM can work in pulling mode without wait for upcall
*/
vhm_req->valid = 1;
atomic_store32(&vhm_req->processed, REQ_STATE_PENDING);
acrn_print_request(vcpu->vcpu_id, vhm_req);
@@ -140,7 +142,7 @@ static void _get_req_info_(struct vhm_request *req, int *id, char *type,
}
switch (req->processed) {
case REQ_STATE_SUCCESS:
case REQ_STATE_COMPLETE:
(void)strcpy_s(state, 16U, "SUCCESS");
break;
case REQ_STATE_PENDING: