* Link the event if it unmasked and not already linked.
*/
if ( !guest_test_bit(d, EVTCHN_FIFO_MASKED, word) &&
+ /*
+ * This also acts as the read counterpart of the smp_wmb() in
+ * map_control_block().
+ */
!guest_test_and_set_bit(d, EVTCHN_FIFO_LINKED, word) )
{
/*
static int map_control_block(struct vcpu *v, uint64_t gfn, uint32_t offset)
{
void *virt;
+ struct evtchn_fifo_control_block *control_block;
unsigned int i;
int rc;
if ( rc < 0 )
return rc;
- v->evtchn_fifo->control_block = virt + offset;
+ control_block = virt + offset;
for ( i = 0; i <= EVTCHN_FIFO_PRIORITY_MIN; i++ )
- v->evtchn_fifo->queue[i].head = &v->evtchn_fifo->control_block->head[i];
+ v->evtchn_fifo->queue[i].head = &control_block->head[i];
+
+ /* All queue heads must have been set before setting the control block. */
+ smp_wmb();
+
+ v->evtchn_fifo->control_block = control_block;
return 0;
}