Skip to content

Commit 5930e96

Browse files
lifeixwenlingz
authored andcommitted
hv: io_req: refine vhm_req status setting
In spite of vhm_req status could be updated in HV and DM on different CPUs, they only change vhm_req status when they detect vhm_req status has been updated by each other. So vhm_req status will not been misconfigured. However, before HV sets vhm_req status to REQ_STATE_PENDING, vhm_req buffer filling should be visible to DM. Add a write memory barrier to guarantee this. Tracked-On: #1842 Signed-off-by: Li, Fei1 <fei1.li@intel.com>
1 parent 1ea3052 commit 5930e96

File tree

2 files changed

+23
-4
lines changed

2 files changed

+23
-4
lines changed

hypervisor/dm/io_req.c

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
#include <vm.h>
77
#include <irq.h>
88
#include <errno.h>
9-
#include <atomic.h>
109
#include <ept.h>
1110
#include <logmsg.h>
1211

@@ -113,6 +112,9 @@ int32_t acrn_insert_request(struct acrn_vcpu *vcpu, const struct io_request *io_
113112
pause_vcpu(vcpu, VCPU_PAUSED);
114113
}
115114

115+
/* Before updating the vhm_req state, enforce all fill vhm_req operations done */
116+
cpu_write_memory_barrier();
117+
116118
/* Must clear the signal before we mark req as pending
117119
* Once we mark it pending, VHM may process req and signal us
118120
* before we perform upcall.
@@ -168,7 +170,7 @@ uint32_t get_vhm_req_state(struct acrn_vm *vm, uint16_t vhm_req_id)
168170
} else {
169171
stac();
170172
vhm_req = &req_buf->req_queue[vhm_req_id];
171-
state = atomic_load32(&vhm_req->processed);
173+
state = vhm_req->processed;
172174
clac();
173175
}
174176

@@ -184,7 +186,13 @@ void set_vhm_req_state(struct acrn_vm *vm, uint16_t vhm_req_id, uint32_t state)
184186
if (req_buf != NULL) {
185187
stac();
186188
vhm_req = &req_buf->req_queue[vhm_req_id];
187-
atomic_store32(&vhm_req->processed, state);
189+
/*
190+
* HV will only set processed to REQ_STATE_PENDING or REQ_STATE_FREE.
191+
* we don't need to sfence here is that even if the SOS/DM sees the previous state,
192+
* the only side effect is that it will defer the processing of the new IOReq.
193+
* It won't lead wrong processing.
194+
*/
195+
vhm_req->processed = state;
188196
clac();
189197
}
190198
}
@@ -245,7 +253,12 @@ static void complete_ioreq(struct acrn_vcpu *vcpu, struct io_request *io_req)
245253
break;
246254
}
247255
}
248-
atomic_store32(&vhm_req->processed, REQ_STATE_FREE);
256+
257+
/*
258+
* Only HV will check whether processed is REQ_STATE_FREE on per-vCPU before inject a ioreq.
259+
* Only HV will set processed to REQ_STATE_FREE when ioreq is done.
260+
*/
261+
vhm_req->processed = REQ_STATE_FREE;
249262
clac();
250263
}
251264

hypervisor/include/arch/x86/cpu.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,12 @@ static inline void cpu_sp_write(uint64_t *stack_ptr)
351351
asm volatile ("movq %0, %%rsp" : : "r"(rsp));
352352
}
353353

354+
/* Synchronizes all write accesses to memory */
355+
static inline void cpu_write_memory_barrier(void)
356+
{
357+
asm volatile ("sfence\n" : : : "memory");
358+
}
359+
354360
/* Synchronizes all read and write accesses to/from memory */
355361
static inline void cpu_memory_barrier(void)
356362
{

0 commit comments

Comments
 (0)