Module Name: src Committed By: bouyer Date: Mon Apr 13 22:54:12 UTC 2020
Modified Files: src/sys/arch/x86/include: cpu.h src/sys/arch/xen/include: evtchn.h src/sys/arch/xen/x86: xen_intr.c xen_ipi.c src/sys/arch/xen/xen: clock.c evtchn.c Log Message: By default, events are bound to CPU 0 (exept for IPIs and VTIMERs which are bound to a different CPU at creation time). Recent MI changes caused the scheduler to choose a different CPU when probing and attaching xennet devices (I guess it's the xenbus thread which runs on a different CPU). This cause the callback to be called on a different CPU than the one expected by the kernel, and the event is ignored. It is handled when the clock causes the callback to be called on the right CPU, which is why xennet still run, but slowly. Change event_set_handler() to do a EVTCHNOP_bind_vcpu if requested to, and make sure we don't do it for IPIs and VIRQs (for theses, the op fails). To generate a diff of this commit: cvs rdiff -u -r1.119 -r1.120 src/sys/arch/x86/include/cpu.h cvs rdiff -u -r1.28 -r1.29 src/sys/arch/xen/include/evtchn.h cvs rdiff -u -r1.21 -r1.22 src/sys/arch/xen/x86/xen_intr.c cvs rdiff -u -r1.35 -r1.36 src/sys/arch/xen/x86/xen_ipi.c cvs rdiff -u -r1.80 -r1.81 src/sys/arch/xen/xen/clock.c cvs rdiff -u -r1.88 -r1.89 src/sys/arch/xen/xen/evtchn.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/x86/include/cpu.h diff -u src/sys/arch/x86/include/cpu.h:1.119 src/sys/arch/x86/include/cpu.h:1.120 --- src/sys/arch/x86/include/cpu.h:1.119 Fri Apr 10 14:35:26 2020 +++ src/sys/arch/x86/include/cpu.h Mon Apr 13 22:54:11 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: cpu.h,v 1.119 2020/04/10 14:35:26 bouyer Exp $ */ +/* $NetBSD: cpu.h,v 1.120 2020/04/13 22:54:11 bouyer Exp $ */ /* * Copyright (c) 1990 The Regents of the University of California. @@ -307,9 +307,6 @@ struct cpu_info { */ uint64_t ci_xen_systime_ns_skew; - /* Xen periodic timer interrupt handle. */ - struct intrhand *ci_xen_timer_intrhand; - /* * Clockframe for timer interrupt handler. * Saved at entry via event callback. Index: src/sys/arch/xen/include/evtchn.h diff -u src/sys/arch/xen/include/evtchn.h:1.28 src/sys/arch/xen/include/evtchn.h:1.29 --- src/sys/arch/xen/include/evtchn.h:1.28 Mon Apr 6 19:26:00 2020 +++ src/sys/arch/xen/include/evtchn.h Mon Apr 13 22:54:12 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: evtchn.h,v 1.28 2020/04/06 19:26:00 jdolecek Exp $ */ +/* $NetBSD: evtchn.h,v 1.29 2020/04/13 22:54:12 bouyer Exp $ */ /* * @@ -42,7 +42,7 @@ unsigned int evtchn_do_event(int, struct void call_evtchn_do_event(int, struct intrframe *); void call_xenevt_event(int); int event_set_handler(int, int (*func)(void *), void *, int, const char *, - const char *, bool); + const char *, bool, bool); int event_remove_handler(int, int (*func)(void *), void *); struct cpu_info; Index: src/sys/arch/xen/x86/xen_intr.c diff -u src/sys/arch/xen/x86/xen_intr.c:1.21 src/sys/arch/xen/x86/xen_intr.c:1.22 --- src/sys/arch/xen/x86/xen_intr.c:1.21 Mon Apr 6 19:26:00 2020 +++ src/sys/arch/xen/x86/xen_intr.c Mon Apr 13 22:54:12 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: xen_intr.c,v 1.21 2020/04/06 19:26:00 jdolecek Exp $ */ +/* $NetBSD: xen_intr.c,v 1.22 2020/04/13 22:54:12 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.21 2020/04/06 19:26:00 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: xen_intr.c,v 1.22 2020/04/13 22:54:12 bouyer Exp $"); #include "opt_multiprocessor.h" @@ -170,7 +170,7 @@ xen_intr_establish_xname(int legacy_irq, sizeof(intrstr_buf)); event_set_handler(pin, handler, arg, level, intrstr, xname, - known_mpsafe); + known_mpsafe, true); rih = kmem_zalloc(sizeof(*rih), cold ? KM_NOSLEEP : KM_SLEEP); if (rih == NULL) { Index: src/sys/arch/xen/x86/xen_ipi.c diff -u src/sys/arch/xen/x86/xen_ipi.c:1.35 src/sys/arch/xen/x86/xen_ipi.c:1.36 --- src/sys/arch/xen/x86/xen_ipi.c:1.35 Sun Dec 1 15:34:46 2019 +++ src/sys/arch/xen/x86/xen_ipi.c Mon Apr 13 22:54:12 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: xen_ipi.c,v 1.35 2019/12/01 15:34:46 ad Exp $ */ +/* $NetBSD: xen_ipi.c,v 1.36 2020/04/13 22:54:12 bouyer Exp $ */ /*- * Copyright (c) 2011, 2019 The NetBSD Foundation, Inc. @@ -33,10 +33,10 @@ /* * Based on: x86/ipi.c - * __KERNEL_RCSID(0, "$NetBSD: xen_ipi.c,v 1.35 2019/12/01 15:34:46 ad Exp $"); + * __KERNEL_RCSID(0, "$NetBSD: xen_ipi.c,v 1.36 2020/04/13 22:54:12 bouyer Exp $"); */ -__KERNEL_RCSID(0, "$NetBSD: xen_ipi.c,v 1.35 2019/12/01 15:34:46 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: xen_ipi.c,v 1.36 2020/04/13 22:54:12 bouyer Exp $"); #include "opt_ddb.h" @@ -98,6 +98,8 @@ xen_ipi_handler(void *arg) ci = curcpu(); regs = arg; + + KASSERT(ci == arg); pending = atomic_swap_32(&ci->ci_ipis, 0); @@ -139,8 +141,8 @@ xen_ipi_init(void) snprintf(intr_xname, sizeof(intr_xname), "%s ipi", device_xname(ci->ci_dev)); - if (xen_intr_establish_xname(-1, &xen_pic, evtchn, IST_LEVEL, IPL_HIGH, - xen_ipi_handler, ci, true, intr_xname) == NULL) { + if (event_set_handler(evtchn, xen_ipi_handler, ci, IPL_HIGH, NULL, + intr_xname, true, false) != 0) { panic("%s: unable to register ipi handler\n", __func__); /* NOTREACHED */ } @@ -314,7 +316,6 @@ xen_ipi_generic(struct cpu_info *ci, str { KASSERT(ci != NULL); KASSERT(intrf != NULL); - ipi_cpu_handler(); } Index: src/sys/arch/xen/xen/clock.c diff -u src/sys/arch/xen/xen/clock.c:1.80 src/sys/arch/xen/xen/clock.c:1.81 --- src/sys/arch/xen/xen/clock.c:1.80 Wed Oct 16 18:29:49 2019 +++ src/sys/arch/xen/xen/clock.c Mon Apr 13 22:54:12 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: clock.c,v 1.80 2019/10/16 18:29:49 christos Exp $ */ +/* $NetBSD: clock.c,v 1.81 2020/04/13 22:54:12 bouyer Exp $ */ /*- * Copyright (c) 2017, 2018 The NetBSD Foundation, Inc. @@ -36,7 +36,7 @@ #endif #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.80 2019/10/16 18:29:49 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.81 2020/04/13 22:54:12 bouyer Exp $"); #include <sys/param.h> #include <sys/types.h> @@ -722,14 +722,13 @@ xen_suspendclocks(struct cpu_info *ci) KASSERT(ci == curcpu()); KASSERT(kpreempt_disabled()); - KASSERT(ci->ci_xen_timer_intrhand != NULL); evtch = unbind_virq_from_evtch(VIRQ_TIMER); KASSERT(evtch != -1); hypervisor_mask_event(evtch); - xen_intr_disestablish(ci->ci_xen_timer_intrhand); - ci->ci_xen_timer_intrhand = NULL; + event_remove_handler(evtch, + __FPTRCAST(int (*)(void *), xen_timer_handler), ci); aprint_verbose("Xen clock: removed event channel %d\n", evtch); @@ -755,7 +754,6 @@ xen_resumeclocks(struct cpu_info *ci) KASSERT(ci == curcpu()); KASSERT(kpreempt_disabled()); - KASSERT(ci->ci_xen_timer_intrhand == NULL); evtch = bind_virq_to_evtch(VIRQ_TIMER); KASSERT(evtch != -1); @@ -763,11 +761,9 @@ xen_resumeclocks(struct cpu_info *ci) snprintf(intr_xname, sizeof(intr_xname), "%s clock", device_xname(ci->ci_dev)); /* XXX sketchy function pointer cast -- fix the API, please */ - ci->ci_xen_timer_intrhand = xen_intr_establish_xname(-1, &xen_pic, - evtch, IST_LEVEL, IPL_CLOCK, + if (event_set_handler(evtch, __FPTRCAST(int (*)(void *), xen_timer_handler), - ci, true, intr_xname); - if (ci->ci_xen_timer_intrhand == NULL) + ci, IPL_CLOCK, NULL, intr_xname, true, false) != 0) panic("failed to establish timer interrupt handler"); hypervisor_unmask_event(evtch); Index: src/sys/arch/xen/xen/evtchn.c diff -u src/sys/arch/xen/xen/evtchn.c:1.88 src/sys/arch/xen/xen/evtchn.c:1.89 --- src/sys/arch/xen/xen/evtchn.c:1.88 Mon Apr 6 19:26:00 2020 +++ src/sys/arch/xen/xen/evtchn.c Mon Apr 13 22:54:12 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: evtchn.c,v 1.88 2020/04/06 19:26:00 jdolecek Exp $ */ +/* $NetBSD: evtchn.c,v 1.89 2020/04/13 22:54:12 bouyer Exp $ */ /* * Copyright (c) 2006 Manuel Bouyer. @@ -54,7 +54,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: evtchn.c,v 1.88 2020/04/06 19:26:00 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: evtchn.c,v 1.89 2020/04/13 22:54:12 bouyer Exp $"); #include "opt_xen.h" #include "isa.h" @@ -764,7 +764,7 @@ pirq_establish(int pirq, int evtch, int ih->arg = arg; if (event_set_handler(evtch, pirq_interrupt, ih, level, intrname, - xname, known_mpsafe) != 0) { + xname, known_mpsafe, true) != 0) { kmem_free(ih, sizeof(struct pintrhand)); return NULL; } @@ -834,12 +834,13 @@ intr_calculatemasks(struct evtsource *ev int event_set_handler(int evtch, int (*func)(void *), void *arg, int level, - const char *intrname, const char *xname, bool mpsafe) + const char *intrname, const char *xname, bool mpsafe, bool bind) { struct cpu_info *ci = curcpu(); /* XXX: pass in ci ? */ struct evtsource *evts; struct intrhand *ih, **ihp; int s; + char intrstr_buf[INTRIDBUF]; #ifdef IRQ_DEBUG printf("event_set_handler IRQ %d handler %p\n", evtch, func); @@ -848,7 +849,7 @@ event_set_handler(int evtch, int (*func) KASSERTMSG(evtch >= 0, "negative evtch: %d", evtch); KASSERTMSG(evtch < NR_EVENT_CHANNELS, "evtch number %d > NR_EVENT_CHANNELS", evtch); - KASSERT(intrname != NULL && xname != NULL); + KASSERT(xname != NULL); #if 0 printf("event_set_handler evtch %d handler %p level %d\n", evtch, @@ -879,6 +880,10 @@ event_set_handler(int evtch, int (*func) /* register handler for event channel */ if (evtsource[evtch] == NULL) { + evtchn_op_t op; + if (intrname == NULL) + intrname = intr_create_intrid(-1, &xen_pic, evtch, + intrstr_buf, sizeof(intrstr_buf)); evts = kmem_zalloc(sizeof (struct evtsource), KM_NOSLEEP); if (evts == NULL) @@ -898,6 +903,15 @@ event_set_handler(int evtch, int (*func) evcnt_attach_dynamic(&evts->ev_evcnt, EVCNT_TYPE_INTR, NULL, device_xname(ci->ci_dev), evts->ev_intrname); + if (bind) { + op.cmd = EVTCHNOP_bind_vcpu; + op.u.bind_vcpu.port = evtch; + op.u.bind_vcpu.vcpu = ci->ci_cpuid; + if (HYPERVISOR_event_channel_op(&op) != 0) { + panic("Failed to bind event %d to " + "VCPU %"PRIuCPUID, evtch, ci->ci_cpuid); + } + } } else { evts = evtsource[evtch]; /* sort by IPL order, higher first */