]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/3.16.3/xen-events-fifo-reset-control-block-and-local-heads-on-resume.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 3.16.3 / xen-events-fifo-reset-control-block-and-local-heads-on-resume.patch
CommitLineData
bf9ffb20
GKH
1From c12784c3d14a2110468ec4d1383f60cfd2665576 Mon Sep 17 00:00:00 2001
2From: David Vrabel <david.vrabel@citrix.com>
3Date: Thu, 31 Jul 2014 16:22:24 +0100
4Subject: xen/events/fifo: reset control block and local HEADs on resume
5
6From: David Vrabel <david.vrabel@citrix.com>
7
8commit c12784c3d14a2110468ec4d1383f60cfd2665576 upstream.
9
10When using the FIFO-based event channel ABI, if the control block or
11the local HEADs are not reset after resuming the guest may see stale
12HEAD values and will fail to traverse the FIFO correctly.
13
14This may prevent one or more VCPUs from receiving any events following
15a resume.
16
17Signed-off-by: David Vrabel <david.vrabel@citrix.com>
18Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
19Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
20
21---
22 drivers/xen/events/events_fifo.c | 48 ++++++++++++++++++++++-----------------
23 1 file changed, 28 insertions(+), 20 deletions(-)
24
25--- a/drivers/xen/events/events_fifo.c
26+++ b/drivers/xen/events/events_fifo.c
27@@ -99,6 +99,25 @@ static unsigned evtchn_fifo_nr_channels(
28 return event_array_pages * EVENT_WORDS_PER_PAGE;
29 }
30
31+static int init_control_block(int cpu,
32+ struct evtchn_fifo_control_block *control_block)
33+{
34+ struct evtchn_fifo_queue *q = &per_cpu(cpu_queue, cpu);
35+ struct evtchn_init_control init_control;
36+ unsigned int i;
37+
38+ /* Reset the control block and the local HEADs. */
39+ clear_page(control_block);
40+ for (i = 0; i < EVTCHN_FIFO_MAX_QUEUES; i++)
41+ q->head[i] = 0;
42+
43+ init_control.control_gfn = virt_to_mfn(control_block);
44+ init_control.offset = 0;
45+ init_control.vcpu = cpu;
46+
47+ return HYPERVISOR_event_channel_op(EVTCHNOP_init_control, &init_control);
48+}
49+
50 static void free_unused_array_pages(void)
51 {
52 unsigned i;
53@@ -323,7 +342,6 @@ static void evtchn_fifo_resume(void)
54
55 for_each_possible_cpu(cpu) {
56 void *control_block = per_cpu(cpu_control_block, cpu);
57- struct evtchn_init_control init_control;
58 int ret;
59
60 if (!control_block)
61@@ -340,12 +358,7 @@ static void evtchn_fifo_resume(void)
62 continue;
63 }
64
65- init_control.control_gfn = virt_to_mfn(control_block);
66- init_control.offset = 0;
67- init_control.vcpu = cpu;
68-
69- ret = HYPERVISOR_event_channel_op(EVTCHNOP_init_control,
70- &init_control);
71+ ret = init_control_block(cpu, control_block);
72 if (ret < 0)
73 BUG();
74 }
75@@ -373,30 +386,25 @@ static const struct evtchn_ops evtchn_op
76 .resume = evtchn_fifo_resume,
77 };
78
79-static int evtchn_fifo_init_control_block(unsigned cpu)
80+static int evtchn_fifo_alloc_control_block(unsigned cpu)
81 {
82- struct page *control_block = NULL;
83- struct evtchn_init_control init_control;
84+ void *control_block = NULL;
85 int ret = -ENOMEM;
86
87- control_block = alloc_page(GFP_KERNEL|__GFP_ZERO);
88+ control_block = (void *)__get_free_page(GFP_KERNEL);
89 if (control_block == NULL)
90 goto error;
91
92- init_control.control_gfn = virt_to_mfn(page_address(control_block));
93- init_control.offset = 0;
94- init_control.vcpu = cpu;
95-
96- ret = HYPERVISOR_event_channel_op(EVTCHNOP_init_control, &init_control);
97+ ret = init_control_block(cpu, control_block);
98 if (ret < 0)
99 goto error;
100
101- per_cpu(cpu_control_block, cpu) = page_address(control_block);
102+ per_cpu(cpu_control_block, cpu) = control_block;
103
104 return 0;
105
106 error:
107- __free_page(control_block);
108+ free_page((unsigned long)control_block);
109 return ret;
110 }
111
112@@ -410,7 +418,7 @@ static int evtchn_fifo_cpu_notification(
113 switch (action) {
114 case CPU_UP_PREPARE:
115 if (!per_cpu(cpu_control_block, cpu))
116- ret = evtchn_fifo_init_control_block(cpu);
117+ ret = evtchn_fifo_alloc_control_block(cpu);
118 break;
119 default:
120 break;
121@@ -427,7 +435,7 @@ int __init xen_evtchn_fifo_init(void)
122 int cpu = get_cpu();
123 int ret;
124
125- ret = evtchn_fifo_init_control_block(cpu);
126+ ret = evtchn_fifo_alloc_control_block(cpu);
127 if (ret < 0)
128 goto out;
129