From owner-svn-src-stable@FreeBSD.ORG Mon Jun 25 07:56:23 2012 Return-Path: Delivered-To: svn-src-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id C6C53106566C; Mon, 25 Jun 2012 07:56:23 +0000 (UTC) (envelope-from fabient@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id B13388FC14; Mon, 25 Jun 2012 07:56:23 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q5P7uNbx059036; Mon, 25 Jun 2012 07:56:23 GMT (envelope-from fabient@svn.freebsd.org) Received: (from fabient@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q5P7uNxw059033; Mon, 25 Jun 2012 07:56:23 GMT (envelope-from fabient@svn.freebsd.org) Message-Id: <201206250756.q5P7uNxw059033@svn.freebsd.org> From: Fabien Thomas Date: Mon, 25 Jun 2012 07:56:23 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org X-SVN-Group: stable-9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r237556 - in stable/9/sys: arm/include dev/hwpmc X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 25 Jun 2012 07:56:23 -0000 Author: fabient Date: Mon Jun 25 07:56:23 2012 New Revision: 237556 URL: http://svn.freebsd.org/changeset/base/237556 Log: MFC r236997: Add ARM callchain support for hwpmc. Modified: stable/9/sys/arm/include/pmc_mdep.h stable/9/sys/dev/hwpmc/hwpmc_arm.c Directory Properties: stable/9/sys/ (props changed) stable/9/sys/dev/ (props changed) Modified: stable/9/sys/arm/include/pmc_mdep.h ============================================================================== --- stable/9/sys/arm/include/pmc_mdep.h Mon Jun 25 07:36:00 2012 (r237555) +++ stable/9/sys/arm/include/pmc_mdep.h Mon Jun 25 07:56:23 2012 (r237556) @@ -50,9 +50,17 @@ union pmc_md_pmc { struct pmc_md_xscale_pmc pm_xscale; }; -#define PMC_TRAPFRAME_TO_PC(TF) ((TF)->tf_pc) -#define PMC_TRAPFRAME_TO_FP(TF) ((TF)->tf_usr_lr) -#define PMC_TRAPFRAME_TO_SP(TF) ((TF)->tf_usr_sp) +#define PMC_IN_KERNEL_STACK(S,START,END) \ + ((S) >= (START) && (S) < (END)) +#define PMC_IN_KERNEL(va) (((va) >= USRSTACK) && \ + ((va) < VM_MAX_KERNEL_ADDRESS)) + +#define PMC_IN_USERSPACE(va) ((va) <= VM_MAXUSER_ADDRESS) + +#define PMC_TRAPFRAME_TO_PC(TF) ((TF)->tf_pc) +#define PMC_TRAPFRAME_TO_FP(TF) ((TF)->tf_r11) +#define PMC_TRAPFRAME_TO_SVC_SP(TF) ((TF)->tf_svc_sp) +#define PMC_TRAPFRAME_TO_USR_SP(TF) ((TF)->tf_usr_sp) /* Build a fake kernel trapframe from current instruction pointer. */ #define PMC_FAKE_TRAPFRAME(TF) \ Modified: stable/9/sys/dev/hwpmc/hwpmc_arm.c ============================================================================== --- stable/9/sys/dev/hwpmc/hwpmc_arm.c Mon Jun 25 07:36:00 2012 (r237555) +++ stable/9/sys/dev/hwpmc/hwpmc_arm.c Mon Jun 25 07:56:23 2012 (r237556) @@ -30,10 +30,16 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include -#include +#include #include +#include + +#include +#include +#include struct pmc_mdep * pmc_md_initialize() @@ -58,27 +64,101 @@ pmc_md_finalize(struct pmc_mdep *md) #endif } -static int -pmc_save_callchain(uintptr_t *cc, int maxsamples, - struct trapframe *tf) -{ - - *cc = PMC_TRAPFRAME_TO_PC(tf); - return (1); -} - int pmc_save_kernel_callchain(uintptr_t *cc, int maxsamples, struct trapframe *tf) { + uintptr_t pc, r, stackstart, stackend, fp; + struct thread *td; + int count; + + KASSERT(TRAPF_USERMODE(tf) == 0,("[arm,%d] not a kernel backtrace", + __LINE__)); + + pc = PMC_TRAPFRAME_TO_PC(tf); + *cc++ = pc; + + if ((td = curthread) == NULL) + return (1); + + if (maxsamples <= 1) + return (1); + + stackstart = (uintptr_t) td->td_kstack; + stackend = (uintptr_t) td->td_kstack + td->td_kstack_pages * PAGE_SIZE; + fp = PMC_TRAPFRAME_TO_FP(tf); + + if (!PMC_IN_KERNEL(pc) || + !PMC_IN_KERNEL_STACK(fp, stackstart, stackend)) + return (1); + + for (count = 1; count < maxsamples; count++) { + /* Use saved lr as pc. */ + r = fp - sizeof(uintptr_t); + if (!PMC_IN_KERNEL_STACK(r, stackstart, stackend)) + break; + pc = *(uintptr_t *)r; + if (!PMC_IN_KERNEL(pc)) + break; + + *cc++ = pc; + + /* Switch to next frame up */ + r = fp - 3 * sizeof(uintptr_t); + if (!PMC_IN_KERNEL_STACK(r, stackstart, stackend)) + break; + fp = *(uintptr_t *)r; + if (!PMC_IN_KERNEL_STACK(fp, stackstart, stackend)) + break; + } - return pmc_save_callchain(cc, maxsamples, tf); + return (count); } int pmc_save_user_callchain(uintptr_t *cc, int maxsamples, struct trapframe *tf) { + uintptr_t pc, r, oldfp, fp; + struct thread *td; + int count; + + KASSERT(TRAPF_USERMODE(tf), ("[x86,%d] Not a user trap frame tf=%p", + __LINE__, (void *) tf)); + + pc = PMC_TRAPFRAME_TO_PC(tf); + *cc++ = pc; + + if ((td = curthread) == NULL) + return (1); + + if (maxsamples <= 1) + return (1); + + oldfp = fp = PMC_TRAPFRAME_TO_FP(tf); + + if (!PMC_IN_USERSPACE(pc) || + !PMC_IN_USERSPACE(fp)) + return (1); + + for (count = 1; count < maxsamples; count++) { + /* Use saved lr as pc. */ + r = fp - sizeof(uintptr_t); + if (copyin((void *)r, &pc, sizeof(pc)) != 0) + break; + if (!PMC_IN_USERSPACE(pc)) + break; + + *cc++ = pc; + + /* Switch to next frame up */ + oldfp = fp; + r = fp - 3 * sizeof(uintptr_t); + if (copyin((void *)r, &fp, sizeof(fp)) != 0) + break; + if (fp < oldfp || !PMC_IN_USERSPACE(fp)) + break; + } - return pmc_save_callchain(cc, maxsamples, tf); + return (count); }