Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/xen Change event_set_handler() to take the target C...
details: https://anonhg.NetBSD.org/src/rev/a37e43c3892a
branches: trunk
changeset: 1009928:a37e43c3892a
user: bouyer <bouyer%NetBSD.org@localhost>
date: Thu May 07 19:48:57 2020 +0000
description:
Change event_set_handler() to take the target CPU parameter. If ci is NULL,
event_set_handler() will choose the CPU and bind the event.
If ci is not NULL the caller is responsible for binding the event.
Use a IPI xcall to register the handlers if needed.
pull in a hack from x86 to force pirq handlers to be mpsafe if registered at
a level != IPL_VM. This is for the com at isa interrupt handler, which
registers at IPL_HIGH and has to way to tell it's mpsafe (taking
KERNEL_LOCK at IPL_HIGH causes deadlocks on MP systems).
diffstat:
sys/arch/xen/include/evtchn.h | 5 +-
sys/arch/xen/x86/xen_intr.c | 10 +-
sys/arch/xen/x86/xen_ipi.c | 6 +-
sys/arch/xen/xen/evtchn.c | 208 ++++++++++++++++++++++++-----------------
sys/arch/xen/xen/xen_clock.c | 6 +-
5 files changed, 137 insertions(+), 98 deletions(-)
diffs (truncated from 401 to 300 lines):
diff -r a459f591fcce -r a37e43c3892a sys/arch/xen/include/evtchn.h
--- a/sys/arch/xen/include/evtchn.h Thu May 07 19:25:57 2020 +0000
+++ b/sys/arch/xen/include/evtchn.h Thu May 07 19:48:57 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: evtchn.h,v 1.31 2020/05/04 15:55:56 jdolecek Exp $ */
+/* $NetBSD: evtchn.h,v 1.32 2020/05/07 19:48:58 bouyer Exp $ */
/*
*
@@ -40,12 +40,11 @@
void call_evtchn_do_event(int, struct intrframe *);
void call_xenevt_event(int);
struct intrhand *event_set_handler(int, int (*func)(void *), void *,
- int, const char *, const char *, bool, bool);
+ int, const char *, const char *, bool, struct cpu_info *);
int event_remove_handler(int, int (*func)(void *), void *);
struct cpu_info;
struct intrhand;
-void event_set_iplhandler(struct cpu_info *, struct intrhand *, int);
extern int debug_port;
extern int xen_debug_handler(void *);
diff -r a459f591fcce -r a37e43c3892a sys/arch/xen/x86/xen_intr.c
--- a/sys/arch/xen/x86/xen_intr.c Thu May 07 19:25:57 2020 +0000
+++ b/sys/arch/xen/x86/xen_intr.c Thu May 07 19:48:57 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: xen_intr.c,v 1.26 2020/05/05 17:02:01 bouyer Exp $ */
+/* $NetBSD: xen_intr.c,v 1.27 2020/05/07 19:48:58 bouyer Exp $ */
/*-
* Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xen_intr.c,v 1.26 2020/05/05 17:02:01 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xen_intr.c,v 1.27 2020/05/07 19:48:58 bouyer Exp $");
#include "opt_multiprocessor.h"
@@ -143,7 +143,7 @@
sizeof(intrstr_buf));
rih = event_set_handler(pin, handler, arg, level,
- intrstr, xname, known_mpsafe, true);
+ intrstr, xname, known_mpsafe, NULL);
if (rih == NULL) {
printf("%s: can't establish interrupt\n", __func__);
@@ -157,6 +157,8 @@
struct pintrhand *pih;
int gsi;
int evtchn;
+ /* the hack below is from x86's intr_establish_xname() */
+ bool mpsafe = (known_mpsafe || level != IPL_VM);
KASSERTMSG(legacy_irq == -1 || (0 <= legacy_irq && legacy_irq < NUM_XEN_IRQS),
"bad legacy IRQ value: %d", legacy_irq);
@@ -190,7 +192,7 @@
}
pih = pirq_establish(gsi, evtchn, handler, arg, level,
- intrstr, xname, known_mpsafe);
+ intrstr, xname, mpsafe);
pih->pic = pic;
return pih;
#endif /* NPCI > 0 || NISA > 0 */
diff -r a459f591fcce -r a37e43c3892a sys/arch/xen/x86/xen_ipi.c
--- a/sys/arch/xen/x86/xen_ipi.c Thu May 07 19:25:57 2020 +0000
+++ b/sys/arch/xen/x86/xen_ipi.c Thu May 07 19:48:57 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: xen_ipi.c,v 1.38 2020/04/25 15:26:17 bouyer Exp $ */
+/* $NetBSD: xen_ipi.c,v 1.39 2020/05/07 19:48:58 bouyer Exp $ */
/*-
* Copyright (c) 2011, 2019 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
* Based on: x86/ipi.c
*/
-__KERNEL_RCSID(0, "$NetBSD: xen_ipi.c,v 1.38 2020/04/25 15:26:17 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xen_ipi.c,v 1.39 2020/05/07 19:48:58 bouyer Exp $");
#include "opt_ddb.h"
@@ -143,7 +143,7 @@
device_xname(ci->ci_dev));
if (event_set_handler(evtchn, xen_ipi_handler, ci, IPL_HIGH, NULL,
- intr_xname, true, false) == NULL) {
+ intr_xname, true, ci) == NULL) {
panic("%s: unable to register ipi handler\n", __func__);
/* NOTREACHED */
}
diff -r a459f591fcce -r a37e43c3892a sys/arch/xen/xen/evtchn.c
--- a/sys/arch/xen/xen/evtchn.c Thu May 07 19:25:57 2020 +0000
+++ b/sys/arch/xen/xen/evtchn.c Thu May 07 19:48:57 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: evtchn.c,v 1.93 2020/05/06 13:43:48 bouyer Exp $ */
+/* $NetBSD: evtchn.c,v 1.94 2020/05/07 19:48:57 bouyer Exp $ */
/*
* Copyright (c) 2006 Manuel Bouyer.
@@ -54,7 +54,7 @@
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: evtchn.c,v 1.93 2020/05/06 13:43:48 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: evtchn.c,v 1.94 2020/05/07 19:48:57 bouyer Exp $");
#include "opt_xen.h"
#include "isa.h"
@@ -722,7 +722,7 @@
ih->arg = arg;
if (event_set_handler(evtch, pirq_interrupt, ih, level, intrname,
- xname, known_mpsafe, true) == NULL) {
+ xname, known_mpsafe, NULL) == NULL) {
kmem_free(ih, sizeof(struct pintrhand));
return NULL;
}
@@ -784,14 +784,81 @@
xen_atomic_clear_bit(&curcpu()->ci_evtmask[0], evtch);
}
+
+struct event_set_handler_args {
+ struct intrhand *ih;
+ struct intrsource *ipls;
+ struct evtsource *evts;
+ int evtch;
+};
+
+/*
+ * Called on bound CPU to handle event_set_handler()
+ * caller (on initiating CPU) holds cpu_lock on our behalf
+ * arg1: struct event_set_handler_args *
+ * arg2: NULL
+ */
+
+static void
+event_set_handler_xcall(void *arg1, void *arg2)
+{
+ struct event_set_handler_args *esh_args = arg1;
+ struct intrhand **ihp, *ih = esh_args->ih;
+ struct evtsource *evts = esh_args->evts;
+
+ const u_long psl = x86_read_psl();
+ x86_disable_intr();
+ /* sort by IPL order, higher first */
+ for (ihp = &evts->ev_handlers; *ihp != NULL;
+ ihp = &((*ihp)->ih_evt_next)) {
+ if ((*ihp)->ih_level < ih->ih_level)
+ break;
+ }
+ /* insert before *ihp */
+ ih->ih_evt_next = *ihp;
+ *ihp = ih;
+#ifndef XENPV
+ evts->ev_isl->is_handlers = evts->ev_handlers;
+#endif
+ /* register per-cpu handler for spllower() */
+ struct cpu_info *ci = ih->ih_cpu;
+ int sir = XEN_IPL2SIR(ih->ih_level);
+ KASSERT(sir >= SIR_XENIPL_VM && sir <= SIR_XENIPL_HIGH);
+
+ KASSERT(ci == curcpu());
+ if (ci->ci_isources[sir] == NULL) {
+ KASSERT(esh_args->ipls != NULL);
+ ci->ci_isources[sir] = esh_args->ipls;
+ }
+ struct intrsource *ipls = ci->ci_isources[sir];
+ ih->ih_next = ipls->is_handlers;
+ ipls->is_handlers = ih;
+ x86_intr_calculatemasks(ci);
+
+ intr_calculatemasks(evts, esh_args->evtch, ci);
+ x86_write_psl(psl);
+}
+
struct intrhand *
event_set_handler(int evtch, int (*func)(void *), void *arg, int level,
- const char *intrname, const char *xname, bool mpsafe, bool bind)
+ const char *intrname, const char *xname, bool mpsafe, struct cpu_info *ci)
{
- struct cpu_info *ci = curcpu(); /* XXX: pass in ci ? */
- struct evtsource *evts;
- struct intrhand *ih, **ihp;
+ struct event_set_handler_args esh_args;
char intrstr_buf[INTRIDBUF];
+ bool bind = false;
+
+ memset(&esh_args, 0, sizeof(esh_args));
+
+ /*
+ * if ci is not specified, we bind to the current cpu.
+ * if ci has been proviced by the called, we assume
+ * he will do the EVTCHNOP_bind_vcpu if needed.
+ */
+ if (ci == NULL) {
+ ci = curcpu();
+ bind = true;
+ }
+
#ifdef IRQ_DEBUG
printf("event_set_handler IRQ %d handler %p\n", evtch, func);
@@ -806,29 +873,47 @@
printf("event_set_handler evtch %d handler %p level %d\n", evtch,
handler, level);
#endif
- ih = kmem_zalloc(sizeof (struct intrhand), KM_NOSLEEP);
- if (ih == NULL)
+ esh_args.ih = kmem_zalloc(sizeof (struct intrhand), KM_NOSLEEP);
+ if (esh_args.ih == NULL)
panic("can't allocate fixed interrupt source");
- ih->ih_pic = &xen_pic;
- ih->ih_level = level;
- ih->ih_fun = ih->ih_realfun = func;
- ih->ih_arg = ih->ih_realarg = arg;
- ih->ih_evt_next = NULL;
- ih->ih_next = NULL;
- ih->ih_cpu = ci;
- ih->ih_pin = evtch;
+ esh_args.ih->ih_pic = &xen_pic;
+ esh_args.ih->ih_level = level;
+ esh_args.ih->ih_fun = esh_args.ih->ih_realfun = func;
+ esh_args.ih->ih_arg = esh_args.ih->ih_realarg = arg;
+ esh_args.ih->ih_evt_next = NULL;
+ esh_args.ih->ih_next = NULL;
+ esh_args.ih->ih_cpu = ci;
+ esh_args.ih->ih_pin = evtch;
#ifdef MULTIPROCESSOR
if (!mpsafe) {
- ih->ih_fun = xen_intr_biglock_wrapper;
- ih->ih_arg = ih;
+ esh_args.ih->ih_fun = xen_intr_biglock_wrapper;
+ esh_args.ih->ih_arg = esh_args.ih;
}
#endif /* MULTIPROCESSOR */
+ KASSERT(mpsafe || level < IPL_HIGH);
mutex_enter(&cpu_lock);
+ /* allocate IPL source if needed */
+ int sir = XEN_IPL2SIR(level);
+ if (ci->ci_isources[sir] == NULL) {
+ struct intrsource *ipls;
+ ipls = kmem_zalloc(sizeof (struct intrsource), KM_NOSLEEP);
+ if (ipls == NULL)
+ panic("can't allocate fixed interrupt source");
+ ipls->is_recurse = xenev_stubs[level - IPL_VM].ist_recurse;
+ ipls->is_resume = xenev_stubs[level - IPL_VM].ist_resume;
+ ipls->is_pic = &xen_pic;
+ esh_args.ipls = ipls;
+ /*
+ * note that we can't set ci_isources here, as
+ * the assembly can't handle is_handlers being NULL
+ */
+ }
/* register handler for event channel */
if (evtsource[evtch] == NULL) {
+ struct evtsource *evts;
evtchn_op_t op;
if (intrname == NULL)
intrname = intr_create_intrid(-1, &xen_pic, evtch,
@@ -838,15 +923,7 @@
if (evts == NULL)
panic("can't allocate fixed interrupt source");
- evts->ev_handlers = ih;
- /*
- * XXX: We're assuming here that ci is the same cpu as
- * the one on which this event/port is bound on. The
- * api needs to be reshuffled so that this assumption
- * is more explicitly implemented.
- */
evts->ev_cpu = ci;
- evtsource[evtch] = evts;
strlcpy(evts->ev_intrname, intrname, sizeof(evts->ev_intrname));
evcnt_attach_dynamic(&evts->ev_evcnt, EVCNT_TYPE_INTR, NULL,
@@ -864,70 +941,31 @@
#ifndef XENPV
evts->ev_isl = intr_allocate_io_intrsource(intrname);
evts->ev_isl->is_pic = &xen_pic;
- evts->ev_isl->is_handlers = evts->ev_handlers;
#endif
- } else {
- evts = evtsource[evtch];
- /* sort by IPL order, higher first */
- for (ihp = &evts->ev_handlers; ; ihp = &((*ihp)->ih_evt_next)) {
- if ((*ihp)->ih_level < ih->ih_level) {
- /* insert before *ihp */
- ih->ih_evt_next = *ihp;
- *ihp = ih;
- break;
- }
Home |
Main Index |
Thread Index |
Old Index