Skip to content

Commit ba31f97

Browse files
committed
Merge tag 'for-linus-5.14-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip
Pull xen fixes from Juergen Gross: "A small cleanup patch and a fix of a rare race in the Xen evtchn driver" * tag 'for-linus-5.14-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip: xen/events: Fix race in set_evtchn_to_irq xen/events: remove redundant initialization of variable irq
2 parents a7a4f1c + 88ca252 commit ba31f97

File tree

1 file changed

+15
-7
lines changed

1 file changed

+15
-7
lines changed

drivers/xen/events/events_base.c

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -198,12 +198,12 @@ static void disable_dynirq(struct irq_data *data);
198198

199199
static DEFINE_PER_CPU(unsigned int, irq_epoch);
200200

201-
static void clear_evtchn_to_irq_row(unsigned row)
201+
static void clear_evtchn_to_irq_row(int *evtchn_row)
202202
{
203203
unsigned col;
204204

205205
for (col = 0; col < EVTCHN_PER_ROW; col++)
206-
WRITE_ONCE(evtchn_to_irq[row][col], -1);
206+
WRITE_ONCE(evtchn_row[col], -1);
207207
}
208208

209209
static void clear_evtchn_to_irq_all(void)
@@ -213,14 +213,15 @@ static void clear_evtchn_to_irq_all(void)
213213
for (row = 0; row < EVTCHN_ROW(xen_evtchn_max_channels()); row++) {
214214
if (evtchn_to_irq[row] == NULL)
215215
continue;
216-
clear_evtchn_to_irq_row(row);
216+
clear_evtchn_to_irq_row(evtchn_to_irq[row]);
217217
}
218218
}
219219

220220
static int set_evtchn_to_irq(evtchn_port_t evtchn, unsigned int irq)
221221
{
222222
unsigned row;
223223
unsigned col;
224+
int *evtchn_row;
224225

225226
if (evtchn >= xen_evtchn_max_channels())
226227
return -EINVAL;
@@ -233,11 +234,18 @@ static int set_evtchn_to_irq(evtchn_port_t evtchn, unsigned int irq)
233234
if (irq == -1)
234235
return 0;
235236

236-
evtchn_to_irq[row] = (int *)get_zeroed_page(GFP_KERNEL);
237-
if (evtchn_to_irq[row] == NULL)
237+
evtchn_row = (int *) __get_free_pages(GFP_KERNEL, 0);
238+
if (evtchn_row == NULL)
238239
return -ENOMEM;
239240

240-
clear_evtchn_to_irq_row(row);
241+
clear_evtchn_to_irq_row(evtchn_row);
242+
243+
/*
244+
* We've prepared an empty row for the mapping. If a different
245+
* thread was faster inserting it, we can drop ours.
246+
*/
247+
if (cmpxchg(&evtchn_to_irq[row], NULL, evtchn_row) != NULL)
248+
free_page((unsigned long) evtchn_row);
241249
}
242250

243251
WRITE_ONCE(evtchn_to_irq[row][col], irq);
@@ -1009,7 +1017,7 @@ static void __unbind_from_irq(unsigned int irq)
10091017
int xen_bind_pirq_gsi_to_irq(unsigned gsi,
10101018
unsigned pirq, int shareable, char *name)
10111019
{
1012-
int irq = -1;
1020+
int irq;
10131021
struct physdev_irq irq_op;
10141022
int ret;
10151023

0 commit comments

Comments
 (0)