1*df62b8a2SRoger Pau Monné /* 2*df62b8a2SRoger Pau Monné * Copyright (c) 2015 Roger Pau Monné <roger.pau@citrix.com> 3*df62b8a2SRoger Pau Monné * All rights reserved. 4*df62b8a2SRoger Pau Monné * 5*df62b8a2SRoger Pau Monné * Redistribution and use in source and binary forms, with or without 6*df62b8a2SRoger Pau Monné * modification, are permitted provided that the following conditions 7*df62b8a2SRoger Pau Monné * are met: 8*df62b8a2SRoger Pau Monné * 1. Redistributions of source code must retain the above copyright 9*df62b8a2SRoger Pau Monné * notice, this list of conditions and the following disclaimer. 10*df62b8a2SRoger Pau Monné * 2. Redistributions in binary form must reproduce the above copyright 11*df62b8a2SRoger Pau Monné * notice, this list of conditions and the following disclaimer in the 12*df62b8a2SRoger Pau Monné * documentation and/or other materials provided with the distribution. 13*df62b8a2SRoger Pau Monné * 14*df62b8a2SRoger Pau Monné * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15*df62b8a2SRoger Pau Monné * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16*df62b8a2SRoger Pau Monné * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17*df62b8a2SRoger Pau Monné * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18*df62b8a2SRoger Pau Monné * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19*df62b8a2SRoger Pau Monné * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20*df62b8a2SRoger Pau Monné * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21*df62b8a2SRoger Pau Monné * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22*df62b8a2SRoger Pau Monné * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23*df62b8a2SRoger Pau Monné * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24*df62b8a2SRoger Pau Monné * SUCH DAMAGE. 25*df62b8a2SRoger Pau Monné */ 26*df62b8a2SRoger Pau Monné 27*df62b8a2SRoger Pau Monné #include <sys/cdefs.h> 28*df62b8a2SRoger Pau Monné __FBSDID("$FreeBSD$"); 29*df62b8a2SRoger Pau Monné 30*df62b8a2SRoger Pau Monné #include "opt_stack.h" 31*df62b8a2SRoger Pau Monné #include "opt_ddb.h" 32*df62b8a2SRoger Pau Monné 33*df62b8a2SRoger Pau Monné #include <sys/param.h> 34*df62b8a2SRoger Pau Monné #include <sys/systm.h> 35*df62b8a2SRoger Pau Monné #include <sys/bus.h> 36*df62b8a2SRoger Pau Monné #include <sys/kernel.h> 37*df62b8a2SRoger Pau Monné #include <sys/module.h> 38*df62b8a2SRoger Pau Monné #include <sys/pcpu.h> 39*df62b8a2SRoger Pau Monné #include <sys/smp.h> 40*df62b8a2SRoger Pau Monné #include <sys/stack.h> 41*df62b8a2SRoger Pau Monné #include <sys/sbuf.h> 42*df62b8a2SRoger Pau Monné 43*df62b8a2SRoger Pau Monné #include <xen/xen-os.h> 44*df62b8a2SRoger Pau Monné #include <xen/xen_intr.h> 45*df62b8a2SRoger Pau Monné #include <xen/hypervisor.h> 46*df62b8a2SRoger Pau Monné 47*df62b8a2SRoger Pau Monné /* 48*df62b8a2SRoger Pau Monné * Xen debug device 49*df62b8a2SRoger Pau Monné * 50*df62b8a2SRoger Pau Monné * Handles the VIRQ_DEBUG interrupt and prints the backtrace of each 51*df62b8a2SRoger Pau Monné * vCPU on the Xen console. 52*df62b8a2SRoger Pau Monné */ 53*df62b8a2SRoger Pau Monné 54*df62b8a2SRoger Pau Monné DPCPU_DEFINE(xen_intr_handle_t, xendebug_handler); 55*df62b8a2SRoger Pau Monné static struct mtx lock; 56*df62b8a2SRoger Pau Monné static struct sbuf *buf; 57*df62b8a2SRoger Pau Monné 58*df62b8a2SRoger Pau Monné static int 59*df62b8a2SRoger Pau Monné xendebug_drain(void *arg, const char *str, int len) 60*df62b8a2SRoger Pau Monné { 61*df62b8a2SRoger Pau Monné 62*df62b8a2SRoger Pau Monné HYPERVISOR_console_write(__DECONST(char *, str), len); 63*df62b8a2SRoger Pau Monné return (len); 64*df62b8a2SRoger Pau Monné } 65*df62b8a2SRoger Pau Monné 66*df62b8a2SRoger Pau Monné extern void 67*df62b8a2SRoger Pau Monné stack_capture(struct stack *st, register_t rbp); 68*df62b8a2SRoger Pau Monné 69*df62b8a2SRoger Pau Monné static int 70*df62b8a2SRoger Pau Monné xendebug_filter(void *arg) 71*df62b8a2SRoger Pau Monné { 72*df62b8a2SRoger Pau Monné #if defined(STACK) && defined(DDB) 73*df62b8a2SRoger Pau Monné struct stack st; 74*df62b8a2SRoger Pau Monné struct trapframe *frame; 75*df62b8a2SRoger Pau Monné 76*df62b8a2SRoger Pau Monné frame = arg; 77*df62b8a2SRoger Pau Monné stack_zero(&st); 78*df62b8a2SRoger Pau Monné stack_save(&st); 79*df62b8a2SRoger Pau Monné 80*df62b8a2SRoger Pau Monné mtx_lock_spin(&lock); 81*df62b8a2SRoger Pau Monné sbuf_clear(buf); 82*df62b8a2SRoger Pau Monné xc_printf("Printing stack trace vCPU%d\n", PCPU_GET(vcpu_id)); 83*df62b8a2SRoger Pau Monné stack_sbuf_print_ddb(buf, &st); 84*df62b8a2SRoger Pau Monné sbuf_finish(buf); 85*df62b8a2SRoger Pau Monné mtx_unlock_spin(&lock); 86*df62b8a2SRoger Pau Monné #endif 87*df62b8a2SRoger Pau Monné 88*df62b8a2SRoger Pau Monné return (FILTER_HANDLED); 89*df62b8a2SRoger Pau Monné } 90*df62b8a2SRoger Pau Monné 91*df62b8a2SRoger Pau Monné static void 92*df62b8a2SRoger Pau Monné xendebug_identify(driver_t *driver, device_t parent) 93*df62b8a2SRoger Pau Monné { 94*df62b8a2SRoger Pau Monné 95*df62b8a2SRoger Pau Monné KASSERT(xen_domain(), 96*df62b8a2SRoger Pau Monné ("Trying to add Xen debug device to non-xen guest")); 97*df62b8a2SRoger Pau Monné 98*df62b8a2SRoger Pau Monné if (xen_hvm_domain() && !xen_vector_callback_enabled) 99*df62b8a2SRoger Pau Monné return; 100*df62b8a2SRoger Pau Monné 101*df62b8a2SRoger Pau Monné if (BUS_ADD_CHILD(parent, 0, "debug", 0) == NULL) 102*df62b8a2SRoger Pau Monné panic("Unable to add Xen debug device."); 103*df62b8a2SRoger Pau Monné } 104*df62b8a2SRoger Pau Monné 105*df62b8a2SRoger Pau Monné static int 106*df62b8a2SRoger Pau Monné xendebug_probe(device_t dev) 107*df62b8a2SRoger Pau Monné { 108*df62b8a2SRoger Pau Monné 109*df62b8a2SRoger Pau Monné device_set_desc(dev, "Xen debug handler"); 110*df62b8a2SRoger Pau Monné return (BUS_PROBE_NOWILDCARD); 111*df62b8a2SRoger Pau Monné } 112*df62b8a2SRoger Pau Monné 113*df62b8a2SRoger Pau Monné static int 114*df62b8a2SRoger Pau Monné xendebug_attach(device_t dev) 115*df62b8a2SRoger Pau Monné { 116*df62b8a2SRoger Pau Monné int i, error; 117*df62b8a2SRoger Pau Monné 118*df62b8a2SRoger Pau Monné mtx_init(&lock, "xen-dbg", NULL, MTX_SPIN); 119*df62b8a2SRoger Pau Monné buf = sbuf_new(NULL, NULL, 1024, SBUF_FIXEDLEN); 120*df62b8a2SRoger Pau Monné if (buf == NULL) 121*df62b8a2SRoger Pau Monné panic("Unable to create sbuf for stack dump"); 122*df62b8a2SRoger Pau Monné sbuf_set_drain(buf, xendebug_drain, NULL); 123*df62b8a2SRoger Pau Monné 124*df62b8a2SRoger Pau Monné /* Bind an event channel to a VIRQ on each VCPU. */ 125*df62b8a2SRoger Pau Monné CPU_FOREACH(i) { 126*df62b8a2SRoger Pau Monné error = xen_intr_bind_virq(dev, VIRQ_DEBUG, i, xendebug_filter, 127*df62b8a2SRoger Pau Monné NULL, NULL, INTR_TYPE_TTY, 128*df62b8a2SRoger Pau Monné DPCPU_ID_PTR(i, xendebug_handler)); 129*df62b8a2SRoger Pau Monné if (error != 0) { 130*df62b8a2SRoger Pau Monné printf("Failed to bind VIRQ_DEBUG to vCPU %d: %d", 131*df62b8a2SRoger Pau Monné i, error); 132*df62b8a2SRoger Pau Monné continue; 133*df62b8a2SRoger Pau Monné } 134*df62b8a2SRoger Pau Monné xen_intr_describe(DPCPU_ID_GET(i, xendebug_handler), "d%d", i); 135*df62b8a2SRoger Pau Monné } 136*df62b8a2SRoger Pau Monné 137*df62b8a2SRoger Pau Monné return (0); 138*df62b8a2SRoger Pau Monné } 139*df62b8a2SRoger Pau Monné 140*df62b8a2SRoger Pau Monné static device_method_t xendebug_methods[] = { 141*df62b8a2SRoger Pau Monné DEVMETHOD(device_identify, xendebug_identify), 142*df62b8a2SRoger Pau Monné DEVMETHOD(device_probe, xendebug_probe), 143*df62b8a2SRoger Pau Monné DEVMETHOD(device_attach, xendebug_attach), 144*df62b8a2SRoger Pau Monné 145*df62b8a2SRoger Pau Monné DEVMETHOD_END 146*df62b8a2SRoger Pau Monné }; 147*df62b8a2SRoger Pau Monné 148*df62b8a2SRoger Pau Monné static driver_t xendebug_driver = { 149*df62b8a2SRoger Pau Monné "debug", 150*df62b8a2SRoger Pau Monné xendebug_methods, 151*df62b8a2SRoger Pau Monné 0, 152*df62b8a2SRoger Pau Monné }; 153*df62b8a2SRoger Pau Monné 154*df62b8a2SRoger Pau Monné devclass_t xendebug_devclass; 155*df62b8a2SRoger Pau Monné 156*df62b8a2SRoger Pau Monné DRIVER_MODULE(xendebug, xenpv, xendebug_driver, xendebug_devclass, 0, 0); 157*df62b8a2SRoger Pau Monné MODULE_DEPEND(xendebug, xenpv, 1, 1, 1); 158