summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/pv/xen.c45
-rw-r--r--sys/dev/pv/xenvar.h3
2 files changed, 46 insertions, 2 deletions
diff --git a/sys/dev/pv/xen.c b/sys/dev/pv/xen.c
index 1e93de05e83..3ceda5540a7 100644
--- a/sys/dev/pv/xen.c
+++ b/sys/dev/pv/xen.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: xen.c,v 1.77 2017/02/08 16:08:06 mikeb Exp $ */
+/* $OpenBSD: xen.c,v 1.78 2017/02/08 16:15:52 mikeb Exp $ */
/*
* Copyright (c) 2015 Mike Belopuhov
@@ -696,6 +696,49 @@ xen_intr_schedule(xen_intr_handle_t xih)
}
}
+static void
+xen_barrier_task(void *arg)
+{
+ int *notdone = arg;
+
+ *notdone = 0;
+ wakeup_one(notdone);
+}
+
+/*
+ * This code achieves two goals: 1) makes sure that *after* masking
+ * the interrupt source we're not getting more task_adds: intr_barrier
+ * will take care of that, and 2) makes sure that the interrupt task
+ * is finished executing the current task and won't be called again:
+ * it sets up a barrier task to await completion of the current task
+ * and relies on the interrupt masking to prevent submission of new
+ * tasks in the future.
+ */
+void
+xen_intr_barrier(xen_intr_handle_t xih)
+{
+ struct xen_softc *sc = xen_sc;
+ struct xen_intsrc *xi;
+ struct sleep_state sls;
+ int notdone = 1;
+ struct task t = TASK_INITIALIZER(xen_barrier_task, &notdone);
+
+ /*
+ * XXX This will need to be revised once intr_barrier starts
+ * using an argument.
+ */
+ intr_barrier(NULL);
+
+ if ((xi = xen_intsrc_acquire(sc, (evtchn_port_t)xih)) != NULL) {
+ task_add(xi->xi_taskq, &t);
+ while (notdone) {
+ sleep_setup(&sls, &notdone, PWAIT, "xenbar");
+ sleep_finish(&sls, notdone);
+ }
+ xen_intsrc_release(sc, xi);
+ }
+}
+
void
xen_intr_signal(xen_intr_handle_t xih)
{
diff --git a/sys/dev/pv/xenvar.h b/sys/dev/pv/xenvar.h
index 48c0a6b3d46..61a4dcb920b 100644
--- a/sys/dev/pv/xenvar.h
+++ b/sys/dev/pv/xenvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: xenvar.h,v 1.48 2017/02/06 21:58:29 mikeb Exp $ */
+/* $OpenBSD: xenvar.h,v 1.49 2017/02/08 16:15:52 mikeb Exp $ */
/*
* Copyright (c) 2015 Mike Belopuhov
@@ -144,6 +144,7 @@ void xen_intr(void);
void xen_intr_ack(void);
void xen_intr_signal(xen_intr_handle_t);
void xen_intr_schedule(xen_intr_handle_t);
+void xen_intr_barrier(xen_intr_handle_t);
int xen_intr_establish(evtchn_port_t, xen_intr_handle_t *, int,
void (*)(void *), void *, char *);
int xen_intr_disestablish(xen_intr_handle_t);