1f263522aSJoseph Koshy /*- 2f263522aSJoseph Koshy * Copyright (c) 2005, Joseph Koshy 3f263522aSJoseph Koshy * All rights reserved. 4f263522aSJoseph Koshy * 5f263522aSJoseph Koshy * Redistribution and use in source and binary forms, with or without 6f263522aSJoseph Koshy * modification, are permitted provided that the following conditions 7f263522aSJoseph Koshy * are met: 8f263522aSJoseph Koshy * 1. Redistributions of source code must retain the above copyright 9f263522aSJoseph Koshy * notice, this list of conditions and the following disclaimer. 10f263522aSJoseph Koshy * 2. Redistributions in binary form must reproduce the above copyright 11f263522aSJoseph Koshy * notice, this list of conditions and the following disclaimer in the 12f263522aSJoseph Koshy * documentation and/or other materials provided with the distribution. 13f263522aSJoseph Koshy * 14f263522aSJoseph Koshy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15f263522aSJoseph Koshy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16f263522aSJoseph Koshy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17f263522aSJoseph Koshy * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18f263522aSJoseph Koshy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19f263522aSJoseph Koshy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20f263522aSJoseph Koshy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21f263522aSJoseph Koshy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22f263522aSJoseph Koshy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23f263522aSJoseph Koshy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24f263522aSJoseph Koshy * SUCH DAMAGE. 25f263522aSJoseph Koshy * 26f263522aSJoseph Koshy */ 27f263522aSJoseph Koshy 28f263522aSJoseph Koshy #include <sys/cdefs.h> 29f263522aSJoseph Koshy __FBSDID("$FreeBSD$"); 30f263522aSJoseph Koshy 31f263522aSJoseph Koshy #include <sys/param.h> 32f263522aSJoseph Koshy #include <sys/pmc.h> 33*790fb4edSFabien Thomas #include <sys/proc.h> 340ce207d2SRui Paulo #include <sys/systm.h> 35f263522aSJoseph Koshy 36*790fb4edSFabien Thomas #include <machine/cpu.h> 370ce207d2SRui Paulo #include <machine/md_var.h> 38*790fb4edSFabien Thomas #include <machine/pmc_mdep.h> 39*790fb4edSFabien Thomas 40*790fb4edSFabien Thomas #include <vm/vm.h> 41*790fb4edSFabien Thomas #include <vm/vm_param.h> 42*790fb4edSFabien Thomas #include <vm/pmap.h> 43f263522aSJoseph Koshy 44f263522aSJoseph Koshy struct pmc_mdep * 45f263522aSJoseph Koshy pmc_md_initialize() 46f263522aSJoseph Koshy { 474cc50ab4SFabien Thomas #ifdef CPU_XSCALE_IXP425 480ce207d2SRui Paulo if (cpu_class == CPU_CLASS_XSCALE) 490ce207d2SRui Paulo return pmc_xscale_initialize(); 500ce207d2SRui Paulo else 514cc50ab4SFabien Thomas #endif 52f263522aSJoseph Koshy return NULL; 53f263522aSJoseph Koshy } 549596916cSJoseph Koshy 55c85e8dcfSJoseph Koshy void 56c85e8dcfSJoseph Koshy pmc_md_finalize(struct pmc_mdep *md) 57c85e8dcfSJoseph Koshy { 584cc50ab4SFabien Thomas #ifdef CPU_XSCALE_IXP425 590ce207d2SRui Paulo if (cpu_class == CPU_CLASS_XSCALE) 600ce207d2SRui Paulo pmc_xscale_finalize(md); 610ce207d2SRui Paulo else 620ce207d2SRui Paulo KASSERT(0, ("[arm,%d] Unknown CPU Class 0x%x", __LINE__, 630ce207d2SRui Paulo cpu_class)); 644cc50ab4SFabien Thomas #endif 654cc50ab4SFabien Thomas } 664cc50ab4SFabien Thomas 679596916cSJoseph Koshy int 689596916cSJoseph Koshy pmc_save_kernel_callchain(uintptr_t *cc, int maxsamples, 699596916cSJoseph Koshy struct trapframe *tf) 709596916cSJoseph Koshy { 71*790fb4edSFabien Thomas uintptr_t pc, r, stackstart, stackend, fp; 72*790fb4edSFabien Thomas struct thread *td; 73*790fb4edSFabien Thomas int count; 744cc50ab4SFabien Thomas 75*790fb4edSFabien Thomas KASSERT(TRAPF_USERMODE(tf) == 0,("[arm,%d] not a kernel backtrace", 76*790fb4edSFabien Thomas __LINE__)); 77*790fb4edSFabien Thomas 78*790fb4edSFabien Thomas pc = PMC_TRAPFRAME_TO_PC(tf); 79*790fb4edSFabien Thomas *cc++ = pc; 80*790fb4edSFabien Thomas 81*790fb4edSFabien Thomas if ((td = curthread) == NULL) 82*790fb4edSFabien Thomas return (1); 83*790fb4edSFabien Thomas 84*790fb4edSFabien Thomas if (maxsamples <= 1) 85*790fb4edSFabien Thomas return (1); 86*790fb4edSFabien Thomas 87*790fb4edSFabien Thomas stackstart = (uintptr_t) td->td_kstack; 88*790fb4edSFabien Thomas stackend = (uintptr_t) td->td_kstack + td->td_kstack_pages * PAGE_SIZE; 89*790fb4edSFabien Thomas fp = PMC_TRAPFRAME_TO_FP(tf); 90*790fb4edSFabien Thomas 91*790fb4edSFabien Thomas if (!PMC_IN_KERNEL(pc) || 92*790fb4edSFabien Thomas !PMC_IN_KERNEL_STACK(fp, stackstart, stackend)) 93*790fb4edSFabien Thomas return (1); 94*790fb4edSFabien Thomas 95*790fb4edSFabien Thomas for (count = 1; count < maxsamples; count++) { 96*790fb4edSFabien Thomas /* Use saved lr as pc. */ 97*790fb4edSFabien Thomas r = fp - sizeof(uintptr_t); 98*790fb4edSFabien Thomas if (!PMC_IN_KERNEL_STACK(r, stackstart, stackend)) 99*790fb4edSFabien Thomas break; 100*790fb4edSFabien Thomas pc = *(uintptr_t *)r; 101*790fb4edSFabien Thomas if (!PMC_IN_KERNEL(pc)) 102*790fb4edSFabien Thomas break; 103*790fb4edSFabien Thomas 104*790fb4edSFabien Thomas *cc++ = pc; 105*790fb4edSFabien Thomas 106*790fb4edSFabien Thomas /* Switch to next frame up */ 107*790fb4edSFabien Thomas r = fp - 3 * sizeof(uintptr_t); 108*790fb4edSFabien Thomas if (!PMC_IN_KERNEL_STACK(r, stackstart, stackend)) 109*790fb4edSFabien Thomas break; 110*790fb4edSFabien Thomas fp = *(uintptr_t *)r; 111*790fb4edSFabien Thomas if (!PMC_IN_KERNEL_STACK(fp, stackstart, stackend)) 112*790fb4edSFabien Thomas break; 113*790fb4edSFabien Thomas } 114*790fb4edSFabien Thomas 115*790fb4edSFabien Thomas return (count); 1169596916cSJoseph Koshy } 1179596916cSJoseph Koshy 1189596916cSJoseph Koshy int 1199596916cSJoseph Koshy pmc_save_user_callchain(uintptr_t *cc, int maxsamples, 1209596916cSJoseph Koshy struct trapframe *tf) 1219596916cSJoseph Koshy { 122*790fb4edSFabien Thomas uintptr_t pc, r, oldfp, fp; 123*790fb4edSFabien Thomas struct thread *td; 124*790fb4edSFabien Thomas int count; 1254cc50ab4SFabien Thomas 126*790fb4edSFabien Thomas KASSERT(TRAPF_USERMODE(tf), ("[x86,%d] Not a user trap frame tf=%p", 127*790fb4edSFabien Thomas __LINE__, (void *) tf)); 128*790fb4edSFabien Thomas 129*790fb4edSFabien Thomas pc = PMC_TRAPFRAME_TO_PC(tf); 130*790fb4edSFabien Thomas *cc++ = pc; 131*790fb4edSFabien Thomas 132*790fb4edSFabien Thomas if ((td = curthread) == NULL) 133*790fb4edSFabien Thomas return (1); 134*790fb4edSFabien Thomas 135*790fb4edSFabien Thomas if (maxsamples <= 1) 136*790fb4edSFabien Thomas return (1); 137*790fb4edSFabien Thomas 138*790fb4edSFabien Thomas oldfp = fp = PMC_TRAPFRAME_TO_FP(tf); 139*790fb4edSFabien Thomas 140*790fb4edSFabien Thomas if (!PMC_IN_USERSPACE(pc) || 141*790fb4edSFabien Thomas !PMC_IN_USERSPACE(fp)) 142*790fb4edSFabien Thomas return (1); 143*790fb4edSFabien Thomas 144*790fb4edSFabien Thomas for (count = 1; count < maxsamples; count++) { 145*790fb4edSFabien Thomas /* Use saved lr as pc. */ 146*790fb4edSFabien Thomas r = fp - sizeof(uintptr_t); 147*790fb4edSFabien Thomas if (copyin((void *)r, &pc, sizeof(pc)) != 0) 148*790fb4edSFabien Thomas break; 149*790fb4edSFabien Thomas if (!PMC_IN_USERSPACE(pc)) 150*790fb4edSFabien Thomas break; 151*790fb4edSFabien Thomas 152*790fb4edSFabien Thomas *cc++ = pc; 153*790fb4edSFabien Thomas 154*790fb4edSFabien Thomas /* Switch to next frame up */ 155*790fb4edSFabien Thomas oldfp = fp; 156*790fb4edSFabien Thomas r = fp - 3 * sizeof(uintptr_t); 157*790fb4edSFabien Thomas if (copyin((void *)r, &fp, sizeof(fp)) != 0) 158*790fb4edSFabien Thomas break; 159*790fb4edSFabien Thomas if (fp < oldfp || !PMC_IN_USERSPACE(fp)) 160*790fb4edSFabien Thomas break; 161*790fb4edSFabien Thomas } 162*790fb4edSFabien Thomas 163*790fb4edSFabien Thomas return (count); 1649596916cSJoseph Koshy } 165