#include <public/event_channel.h>
+union evtchn_fifo_lastq {
+ uint32_t raw;
+ struct {
+ uint8_t last_priority;
+ uint16_t last_vcpu_id;
+ };
+};
+
static inline event_word_t *evtchn_fifo_word_from_port(const struct domain *d,
unsigned int port)
{
struct vcpu *v;
struct evtchn_fifo_queue *q, *old_q;
unsigned int try;
+ union evtchn_fifo_lastq lastq;
for ( try = 0; try < 3; try++ )
{
- v = d->vcpu[evtchn->last_vcpu_id];
- old_q = &v->evtchn_fifo->queue[evtchn->last_priority];
+ lastq.raw = read_atomic(&evtchn->fifo_lastq);
+ v = d->vcpu[lastq.last_vcpu_id];
+ old_q = &v->evtchn_fifo->queue[lastq.last_priority];
spin_lock_irqsave(&old_q->lock, *flags);
- v = d->vcpu[evtchn->last_vcpu_id];
- q = &v->evtchn_fifo->queue[evtchn->last_priority];
+ v = d->vcpu[lastq.last_vcpu_id];
+ q = &v->evtchn_fifo->queue[lastq.last_priority];
if ( old_q == q )
return old_q;
/* Moved to a different queue? */
if ( old_q != q )
{
- evtchn->last_vcpu_id = v->vcpu_id;
- evtchn->last_priority = q->priority;
+ union evtchn_fifo_lastq lastq = { };
+
+ lastq.last_vcpu_id = v->vcpu_id;
+ lastq.last_priority = q->priority;
+ write_atomic(&evtchn->fifo_lastq, lastq.raw);
spin_unlock_irqrestore(&old_q->lock, flags);
spin_lock_irqsave(&q->lock, flags);