[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 1/3] xen/events/fifo: reset control block and local HEADs on resume



When using the FIFO-based event channel ABI, if the control block or
the local HEADs are not reset after resuming the guest may see stale
HEAD values and will fail to traverse the FIFO correctly.

This may prevent one or more VCPUs from receiving any events following
a resume.

Signed-off-by: David Vrabel <david.vrabel@xxxxxxxxxx>
Cc: stable@xxxxxxxxxxxxxxx
---
 drivers/xen/events/events_fifo.c |   41 ++++++++++++++++++++++----------------
 1 file changed, 24 insertions(+), 17 deletions(-)

diff --git a/drivers/xen/events/events_fifo.c b/drivers/xen/events/events_fifo.c
index 84b4bfb..7dc0a7c 100644
--- a/drivers/xen/events/events_fifo.c
+++ b/drivers/xen/events/events_fifo.c
@@ -100,6 +100,24 @@ static unsigned evtchn_fifo_nr_channels(void)
        return event_array_pages * EVENT_WORDS_PER_PAGE;
 }
 
+static int init_control_block(int cpu, void *control_block)
+{
+       struct evtchn_fifo_queue *q = &per_cpu(cpu_queue, cpu);
+       struct evtchn_init_control init_control;
+       unsigned int i;
+
+       /* Reset the control block and the local HEADs. */
+       clear_page(control_block);
+       for (i = 0; i < EVTCHN_FIFO_MAX_QUEUES; i++)
+               q->head[i] = 0;
+
+       init_control.control_gfn = virt_to_mfn(control_block);
+       init_control.offset      = 0;
+       init_control.vcpu        = cpu;
+
+       return HYPERVISOR_event_channel_op(EVTCHNOP_init_control, 
&init_control);
+}
+
 static void free_unused_array_pages(void)
 {
        unsigned i;
@@ -324,7 +342,6 @@ static void evtchn_fifo_resume(void)
 
        for_each_possible_cpu(cpu) {
                void *control_block = per_cpu(cpu_control_block, cpu);
-               struct evtchn_init_control init_control;
                int ret;
 
                if (!control_block)
@@ -341,12 +358,7 @@ static void evtchn_fifo_resume(void)
                        continue;
                }
 
-               init_control.control_gfn = virt_to_mfn(control_block);
-               init_control.offset = 0;
-               init_control.vcpu = cpu;
-
-               ret = HYPERVISOR_event_channel_op(EVTCHNOP_init_control,
-                                                 &init_control);
+               ret = init_control_block(cpu, control_block);
                if (ret < 0)
                        BUG();
        }
@@ -376,28 +388,23 @@ static const struct evtchn_ops evtchn_ops_fifo = {
 
 static int evtchn_fifo_init_control_block(unsigned cpu)
 {
-       struct page *control_block = NULL;
-       struct evtchn_init_control init_control;
+       void *control_block = NULL;
        int ret = -ENOMEM;
 
-       control_block = alloc_page(GFP_KERNEL|__GFP_ZERO);
+       control_block = (void *)__get_free_page(GFP_KERNEL);
        if (control_block == NULL)
                goto error;
 
-       init_control.control_gfn = virt_to_mfn(page_address(control_block));
-       init_control.offset      = 0;
-       init_control.vcpu        = cpu;
-
-       ret = HYPERVISOR_event_channel_op(EVTCHNOP_init_control, &init_control);
+       ret = init_control_block(cpu, control_block);
        if (ret < 0)
                goto error;
 
-       per_cpu(cpu_control_block, cpu) = page_address(control_block);
+       per_cpu(cpu_control_block, cpu) = control_block;
 
        return 0;
 
   error:
-       __free_page(control_block);
+       free_page((unsigned long)control_block);
        return ret;
 }
 
-- 
1.7.10.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.