Add ARM callchain support for hwpmc.
Sponsored by: NETASQ MFC after: 3 days
This commit is contained in:
parent
46f5390139
commit
790fb4edf2
@ -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) \
|
||||
|
@ -30,10 +30,16 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/pmc.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <machine/pmc_mdep.h>
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/md_var.h>
|
||||
#include <machine/pmc_mdep.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/pmap.h>
|
||||
|
||||
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;
|
||||
|
||||
return pmc_save_callchain(cc, maxsamples, tf);
|
||||
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 (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;
|
||||
|
||||
return pmc_save_callchain(cc, maxsamples, tf);
|
||||
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 (count);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user