aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVladimir Murzin <murzin.v@gmail.com>2014-04-27 05:09:12 -0400
committerDavid Vrabel <david.vrabel@citrix.com>2014-04-28 06:09:40 -0400
commit05a812ac474d0d6aef6d54b66bb08b81abde79c6 (patch)
tree016ab4001a17411758548428af3c4cced70cb052
parent063aa8e68e53cc0d0961ea90c12cea40c6b94828 (diff)
xen/events/fifo: correctly align bitops
FIFO event channels require bitops on 32-bit aligned values (the event words). Linux's bitops require unsigned long alignment which may be 64-bits. On arm64 an incorrectly unaligned access will fault. Fix this by aligning the bitops along with an adjustment for bit position and using an unsigned long for the local copy of the ready word. Cc: stable@vger.kernel.org Signed-off-by: Vladimir Murzin <murzin.v@gmail.com> Tested-by: Pranavkumar Sawargaonkar <pranavkumar@linaro.org> Reviewed-by: Ian Campbell <ian.campbell@citrix.com> Signed-off-by: David Vrabel <david.vrabel@citrix.com>
-rw-r--r--drivers/xen/events/events_fifo.c41
1 files changed, 30 insertions, 11 deletions
diff --git a/drivers/xen/events/events_fifo.c b/drivers/xen/events/events_fifo.c
index 96109a9972b6..84b4bfb84344 100644
--- a/drivers/xen/events/events_fifo.c
+++ b/drivers/xen/events/events_fifo.c
@@ -66,7 +66,22 @@ static DEFINE_PER_CPU(struct evtchn_fifo_queue, cpu_queue);
66static event_word_t *event_array[MAX_EVENT_ARRAY_PAGES] __read_mostly; 66static event_word_t *event_array[MAX_EVENT_ARRAY_PAGES] __read_mostly;
67static unsigned event_array_pages __read_mostly; 67static unsigned event_array_pages __read_mostly;
68 68
69/*
70 * sync_set_bit() and friends must be unsigned long aligned on non-x86
71 * platforms.
72 */
73#if !defined(CONFIG_X86) && BITS_PER_LONG > 32
74
75#define BM(w) (unsigned long *)((unsigned long)w & ~0x7UL)
76#define EVTCHN_FIFO_BIT(b, w) \
77 (((unsigned long)w & 0x4UL) ? (EVTCHN_FIFO_ ##b + 32) : EVTCHN_FIFO_ ##b)
78
79#else
80
69#define BM(w) ((unsigned long *)(w)) 81#define BM(w) ((unsigned long *)(w))
82#define EVTCHN_FIFO_BIT(b, w) EVTCHN_FIFO_ ##b
83
84#endif
70 85
71static inline event_word_t *event_word_from_port(unsigned port) 86static inline event_word_t *event_word_from_port(unsigned port)
72{ 87{
@@ -161,33 +176,38 @@ static void evtchn_fifo_bind_to_cpu(struct irq_info *info, unsigned cpu)
161static void evtchn_fifo_clear_pending(unsigned port) 176static void evtchn_fifo_clear_pending(unsigned port)
162{ 177{
163 event_word_t *word = event_word_from_port(port); 178 event_word_t *word = event_word_from_port(port);
164 sync_clear_bit(EVTCHN_FIFO_PENDING, BM(word)); 179 sync_clear_bit(EVTCHN_FIFO_BIT(PENDING, word), BM(word));
165} 180}
166 181
167static void evtchn_fifo_set_pending(unsigned port) 182static void evtchn_fifo_set_pending(unsigned port)
168{ 183{
169 event_word_t *word = event_word_from_port(port); 184 event_word_t *word = event_word_from_port(port);
170 sync_set_bit(EVTCHN_FIFO_PENDING, BM(word)); 185 sync_set_bit(EVTCHN_FIFO_BIT(PENDING, word), BM(word));
171} 186}
172 187
173static bool evtchn_fifo_is_pending(unsigned port) 188static bool evtchn_fifo_is_pending(unsigned port)
174{ 189{
175 event_word_t *word = event_word_from_port(port); 190 event_word_t *word = event_word_from_port(port);
176 return sync_test_bit(EVTCHN_FIFO_PENDING, BM(word)); 191 return sync_test_bit(EVTCHN_FIFO_BIT(PENDING, word), BM(word));
177} 192}
178 193
179static bool evtchn_fifo_test_and_set_mask(unsigned port) 194static bool evtchn_fifo_test_and_set_mask(unsigned port)
180{ 195{
181 event_word_t *word = event_word_from_port(port); 196 event_word_t *word = event_word_from_port(port);
182 return sync_test_and_set_bit(EVTCHN_FIFO_MASKED, BM(word)); 197 return sync_test_and_set_bit(EVTCHN_FIFO_BIT(MASKED, word), BM(word));
183} 198}
184 199
185static void evtchn_fifo_mask(unsigned port) 200static void evtchn_fifo_mask(unsigned port)
186{ 201{
187 event_word_t *word = event_word_from_port(port); 202 event_word_t *word = event_word_from_port(port);
188 sync_set_bit(EVTCHN_FIFO_MASKED, BM(word)); 203 sync_set_bit(EVTCHN_FIFO_BIT(MASKED, word), BM(word));
189} 204}
190 205
206static bool evtchn_fifo_is_masked(unsigned port)
207{
208 event_word_t *word = event_word_from_port(port);
209 return sync_test_bit(EVTCHN_FIFO_BIT(MASKED, word), BM(word));
210}
191/* 211/*
192 * Clear MASKED, spinning if BUSY is set. 212 * Clear MASKED, spinning if BUSY is set.
193 */ 213 */
@@ -211,7 +231,7 @@ static void evtchn_fifo_unmask(unsigned port)
211 BUG_ON(!irqs_disabled()); 231 BUG_ON(!irqs_disabled());
212 232
213 clear_masked(word); 233 clear_masked(word);
214 if (sync_test_bit(EVTCHN_FIFO_PENDING, BM(word))) { 234 if (evtchn_fifo_is_pending(port)) {
215 struct evtchn_unmask unmask = { .port = port }; 235 struct evtchn_unmask unmask = { .port = port };
216 (void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask); 236 (void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask);
217 } 237 }
@@ -243,7 +263,7 @@ static void handle_irq_for_port(unsigned port)
243 263
244static void consume_one_event(unsigned cpu, 264static void consume_one_event(unsigned cpu,
245 struct evtchn_fifo_control_block *control_block, 265 struct evtchn_fifo_control_block *control_block,
246 unsigned priority, uint32_t *ready) 266 unsigned priority, unsigned long *ready)
247{ 267{
248 struct evtchn_fifo_queue *q = &per_cpu(cpu_queue, cpu); 268 struct evtchn_fifo_queue *q = &per_cpu(cpu_queue, cpu);
249 uint32_t head; 269 uint32_t head;
@@ -273,10 +293,9 @@ static void consume_one_event(unsigned cpu,
273 * copy of the ready word. 293 * copy of the ready word.
274 */ 294 */
275 if (head == 0) 295 if (head == 0)
276 clear_bit(priority, BM(ready)); 296 clear_bit(priority, ready);
277 297
278 if (sync_test_bit(EVTCHN_FIFO_PENDING, BM(word)) 298 if (evtchn_fifo_is_pending(port) && !evtchn_fifo_is_masked(port))
279 && !sync_test_bit(EVTCHN_FIFO_MASKED, BM(word)))
280 handle_irq_for_port(port); 299 handle_irq_for_port(port);
281 300
282 q->head[priority] = head; 301 q->head[priority] = head;
@@ -285,7 +304,7 @@ static void consume_one_event(unsigned cpu,
285static void evtchn_fifo_handle_events(unsigned cpu) 304static void evtchn_fifo_handle_events(unsigned cpu)
286{ 305{
287 struct evtchn_fifo_control_block *control_block; 306 struct evtchn_fifo_control_block *control_block;
288 uint32_t ready; 307 unsigned long ready;
289 unsigned q; 308 unsigned q;
290 309
291 control_block = per_cpu(cpu_control_block, cpu); 310 control_block = per_cpu(cpu_control_block, cpu);