hwpmc: use kstack_contains()
This existing helper function is preferable to the hand-rolled calculation of the kstack bounds. Make some small style improvements while here. Notably, rename every instance of "r", the return address, to "ra". Tidy the includes in the affected files. Reviewed by: jkoshy MFC after: 2 weeks Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D39909
This commit is contained in:
parent
5387495773
commit
aba91805aa
@ -109,11 +109,9 @@ union pmc_md_pmc {
|
|||||||
((PC) >= (uintptr_t) start_exceptions && \
|
((PC) >= (uintptr_t) start_exceptions && \
|
||||||
(PC) < (uintptr_t) end_exceptions)
|
(PC) < (uintptr_t) end_exceptions)
|
||||||
|
|
||||||
#define PMC_IN_KERNEL_STACK(S,START,END) \
|
#define PMC_IN_KERNEL_STACK(va) kstack_contains(curthread, (va), sizeof(va))
|
||||||
((S) >= (START) && (S) < (END))
|
#define PMC_IN_KERNEL(va) INKERNEL(va)
|
||||||
#define PMC_IN_KERNEL(va) INKERNEL(va)
|
#define PMC_IN_USERSPACE(va) ((va) <= VM_MAXUSER_ADDRESS)
|
||||||
|
|
||||||
#define PMC_IN_USERSPACE(va) ((va) <= VM_MAXUSER_ADDRESS)
|
|
||||||
|
|
||||||
/* Build a fake kernel trapframe from current instruction pointer. */
|
/* Build a fake kernel trapframe from current instruction pointer. */
|
||||||
#define PMC_FAKE_TRAPFRAME(TF) \
|
#define PMC_FAKE_TRAPFRAME(TF) \
|
||||||
|
@ -52,11 +52,9 @@ union pmc_md_pmc {
|
|||||||
struct pmc_md_armv7_pmc pm_armv7;
|
struct pmc_md_armv7_pmc pm_armv7;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PMC_IN_KERNEL_STACK(S,START,END) \
|
#define PMC_IN_KERNEL_STACK(va) kstack_contains(curthread, (va), sizeof(va))
|
||||||
((S) >= (START) && (S) < (END))
|
|
||||||
#define PMC_IN_KERNEL(va) INKERNEL((va))
|
#define PMC_IN_KERNEL(va) INKERNEL((va))
|
||||||
|
#define PMC_IN_USERSPACE(va) ((va) <= VM_MAXUSER_ADDRESS)
|
||||||
#define PMC_IN_USERSPACE(va) ((va) <= VM_MAXUSER_ADDRESS)
|
|
||||||
|
|
||||||
#define PMC_TRAPFRAME_TO_PC(TF) ((TF)->tf_pc)
|
#define PMC_TRAPFRAME_TO_PC(TF) ((TF)->tf_pc)
|
||||||
#define PMC_TRAPFRAME_TO_FP(TF) ((TF)->tf_r11)
|
#define PMC_TRAPFRAME_TO_FP(TF) ((TF)->tf_r11)
|
||||||
|
@ -66,12 +66,11 @@ union pmc_md_pmc {
|
|||||||
struct pmc_md_dmc620_pmc pm_dmc620;
|
struct pmc_md_dmc620_pmc pm_dmc620;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PMC_IN_KERNEL_STACK(S,START,END) \
|
#define PMC_IN_KERNEL_STACK(va) kstack_contains(curthread, (va), sizeof(va))
|
||||||
((S) >= (START) && (S) < (END))
|
|
||||||
#define PMC_IN_KERNEL(va) INKERNEL((va))
|
#define PMC_IN_KERNEL(va) INKERNEL((va))
|
||||||
#define PMC_IN_USERSPACE(va) ((va) <= VM_MAXUSER_ADDRESS)
|
#define PMC_IN_USERSPACE(va) ((va) <= VM_MAXUSER_ADDRESS)
|
||||||
#define PMC_TRAPFRAME_TO_PC(TF) ((TF)->tf_elr)
|
#define PMC_TRAPFRAME_TO_PC(TF) ((TF)->tf_elr)
|
||||||
#define PMC_TRAPFRAME_TO_FP(TF) ((TF)->tf_x[29])
|
#define PMC_TRAPFRAME_TO_FP(TF) ((TF)->tf_x[29])
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prototypes
|
* Prototypes
|
||||||
|
@ -31,18 +31,17 @@
|
|||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/pmc.h>
|
|
||||||
#include <sys/proc.h>
|
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
|
#include <sys/pmc.h>
|
||||||
|
|
||||||
|
#include <vm/vm.h>
|
||||||
|
#include <vm/pmap.h>
|
||||||
|
|
||||||
#include <machine/cpu.h>
|
#include <machine/cpu.h>
|
||||||
#include <machine/md_var.h>
|
#include <machine/md_var.h>
|
||||||
#include <machine/pmc_mdep.h>
|
#include <machine/pmc_mdep.h>
|
||||||
#include <machine/stack.h>
|
#include <machine/stack.h>
|
||||||
|
#include <machine/vmparam.h>
|
||||||
#include <vm/vm.h>
|
|
||||||
#include <vm/vm_param.h>
|
|
||||||
#include <vm/pmap.h>
|
|
||||||
|
|
||||||
/* XXX: Userland code compiled with gcc will need an heuristic
|
/* XXX: Userland code compiled with gcc will need an heuristic
|
||||||
* to be correctly detected.
|
* to be correctly detected.
|
||||||
@ -78,45 +77,39 @@ int
|
|||||||
pmc_save_kernel_callchain(uintptr_t *cc, int maxsamples,
|
pmc_save_kernel_callchain(uintptr_t *cc, int maxsamples,
|
||||||
struct trapframe *tf)
|
struct trapframe *tf)
|
||||||
{
|
{
|
||||||
uintptr_t pc, r, stackstart, stackend, fp;
|
uintptr_t pc, ra, fp;
|
||||||
struct thread *td;
|
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
KASSERT(TRAPF_USERMODE(tf) == 0,("[arm,%d] not a kernel backtrace",
|
KASSERT(TRAPF_USERMODE(tf) == 0,("[arm,%d] not a kernel backtrace",
|
||||||
__LINE__));
|
__LINE__));
|
||||||
|
|
||||||
td = curthread;
|
|
||||||
pc = PMC_TRAPFRAME_TO_PC(tf);
|
pc = PMC_TRAPFRAME_TO_PC(tf);
|
||||||
*cc++ = pc;
|
*cc++ = pc;
|
||||||
|
|
||||||
if (maxsamples <= 1)
|
if (maxsamples <= 1)
|
||||||
return (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);
|
fp = PMC_TRAPFRAME_TO_FP(tf);
|
||||||
|
if (!PMC_IN_KERNEL(pc) || !PMC_IN_KERNEL_STACK(fp))
|
||||||
if (!PMC_IN_KERNEL(pc) ||
|
|
||||||
!PMC_IN_KERNEL_STACK(fp, stackstart, stackend))
|
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
for (count = 1; count < maxsamples; count++) {
|
for (count = 1; count < maxsamples; count++) {
|
||||||
/* Use saved lr as pc. */
|
/* Use saved lr as pc. */
|
||||||
r = fp + PC_OFF * sizeof(uintptr_t);
|
ra = fp + PC_OFF * sizeof(uintptr_t);
|
||||||
if (!PMC_IN_KERNEL_STACK(r, stackstart, stackend))
|
if (!PMC_IN_KERNEL_STACK(ra))
|
||||||
break;
|
break;
|
||||||
pc = *(uintptr_t *)r;
|
pc = *(uintptr_t *)ra;
|
||||||
if (!PMC_IN_KERNEL(pc))
|
if (!PMC_IN_KERNEL(pc))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
*cc++ = pc;
|
*cc++ = pc;
|
||||||
|
|
||||||
/* Switch to next frame up */
|
/* Switch to next frame up */
|
||||||
r = fp + FP_OFF * sizeof(uintptr_t);
|
ra = fp + FP_OFF * sizeof(uintptr_t);
|
||||||
if (!PMC_IN_KERNEL_STACK(r, stackstart, stackend))
|
if (!PMC_IN_KERNEL_STACK(ra))
|
||||||
break;
|
break;
|
||||||
fp = *(uintptr_t *)r;
|
fp = *(uintptr_t *)ra;
|
||||||
if (!PMC_IN_KERNEL_STACK(fp, stackstart, stackend))
|
if (!PMC_IN_KERNEL_STACK(fp))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,18 +31,17 @@
|
|||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/pmc.h>
|
|
||||||
#include <sys/proc.h>
|
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
|
#include <sys/pmc.h>
|
||||||
|
|
||||||
|
#include <vm/vm.h>
|
||||||
|
#include <vm/pmap.h>
|
||||||
|
|
||||||
#include <machine/cpu.h>
|
#include <machine/cpu.h>
|
||||||
#include <machine/md_var.h>
|
#include <machine/md_var.h>
|
||||||
#include <machine/pmc_mdep.h>
|
#include <machine/pmc_mdep.h>
|
||||||
#include <machine/stack.h>
|
#include <machine/stack.h>
|
||||||
|
#include <machine/vmparam.h>
|
||||||
#include <vm/vm.h>
|
|
||||||
#include <vm/vm_param.h>
|
|
||||||
#include <vm/pmap.h>
|
|
||||||
|
|
||||||
struct pmc_mdep *
|
struct pmc_mdep *
|
||||||
pmc_md_initialize(void)
|
pmc_md_initialize(void)
|
||||||
@ -59,30 +58,22 @@ pmc_md_finalize(struct pmc_mdep *md)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
pmc_save_kernel_callchain(uintptr_t *cc, int maxsamples,
|
pmc_save_kernel_callchain(uintptr_t *cc, int maxsamples, struct trapframe *tf)
|
||||||
struct trapframe *tf)
|
|
||||||
{
|
{
|
||||||
struct unwind_state frame;
|
struct unwind_state frame;
|
||||||
uintptr_t stackstart, stackend;
|
|
||||||
struct thread *td;
|
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
KASSERT(TRAPF_USERMODE(tf) == 0,("[arm64,%d] not a kernel backtrace",
|
KASSERT(TRAPF_USERMODE(tf) == 0,("[arm64,%d] not a kernel backtrace",
|
||||||
__LINE__));
|
__LINE__));
|
||||||
|
|
||||||
td = curthread;
|
|
||||||
frame.pc = PMC_TRAPFRAME_TO_PC(tf);
|
frame.pc = PMC_TRAPFRAME_TO_PC(tf);
|
||||||
*cc++ = frame.pc;
|
*cc++ = frame.pc;
|
||||||
|
|
||||||
if (maxsamples <= 1)
|
if (maxsamples <= 1)
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
stackstart = (uintptr_t) td->td_kstack;
|
|
||||||
stackend = (uintptr_t) td->td_kstack + td->td_kstack_pages * PAGE_SIZE;
|
|
||||||
frame.fp = PMC_TRAPFRAME_TO_FP(tf);
|
frame.fp = PMC_TRAPFRAME_TO_FP(tf);
|
||||||
|
if (!PMC_IN_KERNEL(frame.pc) || !PMC_IN_KERNEL_STACK(frame.fp))
|
||||||
if (!PMC_IN_KERNEL(frame.pc) ||
|
|
||||||
!PMC_IN_KERNEL_STACK(frame.fp, stackstart, stackend))
|
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
for (count = 1; count < maxsamples; count++) {
|
for (count = 1; count < maxsamples; count++) {
|
||||||
|
@ -34,21 +34,22 @@
|
|||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
#include <sys/systm.h>
|
||||||
#include <sys/bus.h>
|
#include <sys/bus.h>
|
||||||
#include <sys/pmc.h>
|
#include <sys/pmc.h>
|
||||||
#include <sys/proc.h>
|
|
||||||
#include <sys/systm.h>
|
#include <vm/vm.h>
|
||||||
|
#include <vm/pmap.h>
|
||||||
|
|
||||||
#include <machine/cpu.h>
|
#include <machine/cpu.h>
|
||||||
#include <machine/cputypes.h>
|
#include <machine/cputypes.h>
|
||||||
#include <machine/intr_machdep.h>
|
#include <machine/intr_machdep.h> /* For x86/apicvar.h */
|
||||||
#include <x86/apicvar.h>
|
|
||||||
#include <machine/pmc_mdep.h>
|
|
||||||
#include <machine/md_var.h>
|
#include <machine/md_var.h>
|
||||||
|
#include <machine/pmc_mdep.h>
|
||||||
|
#include <machine/stack.h>
|
||||||
|
#include <machine/vmparam.h>
|
||||||
|
|
||||||
#include <vm/vm.h>
|
#include <x86/apicvar.h>
|
||||||
#include <vm/vm_param.h>
|
|
||||||
#include <vm/pmap.h>
|
|
||||||
|
|
||||||
#include "hwpmc_soft.h"
|
#include "hwpmc_soft.h"
|
||||||
|
|
||||||
@ -155,36 +156,29 @@ pmc_save_user_callchain(uintptr_t *cc, int nframes, struct trapframe *tf)
|
|||||||
int __nosanitizeaddress __nosanitizememory
|
int __nosanitizeaddress __nosanitizememory
|
||||||
pmc_save_kernel_callchain(uintptr_t *cc, int nframes, struct trapframe *tf)
|
pmc_save_kernel_callchain(uintptr_t *cc, int nframes, struct trapframe *tf)
|
||||||
{
|
{
|
||||||
int n;
|
uintptr_t fp, pc, ra, sp;
|
||||||
uint32_t instr;
|
uint32_t instr;
|
||||||
uintptr_t fp, pc, r, sp, stackstart, stackend;
|
int n;
|
||||||
struct thread *td;
|
|
||||||
|
|
||||||
KASSERT(TRAPF_USERMODE(tf) == 0,("[x86,%d] not a kernel backtrace",
|
KASSERT(TRAPF_USERMODE(tf) == 0,("[x86,%d] not a kernel backtrace",
|
||||||
__LINE__));
|
__LINE__));
|
||||||
|
|
||||||
td = curthread;
|
|
||||||
pc = PMC_TRAPFRAME_TO_PC(tf);
|
pc = PMC_TRAPFRAME_TO_PC(tf);
|
||||||
fp = PMC_TRAPFRAME_TO_FP(tf);
|
fp = PMC_TRAPFRAME_TO_FP(tf);
|
||||||
sp = PMC_TRAPFRAME_TO_KERNEL_SP(tf);
|
sp = PMC_TRAPFRAME_TO_KERNEL_SP(tf);
|
||||||
|
|
||||||
*cc++ = pc;
|
*cc++ = pc;
|
||||||
r = fp + sizeof(uintptr_t); /* points to return address */
|
ra = fp + sizeof(uintptr_t); /* points to return address */
|
||||||
|
|
||||||
if (nframes <= 1)
|
if (nframes <= 1)
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
stackstart = (uintptr_t) td->td_kstack;
|
if (PMC_IN_TRAP_HANDLER(pc) || !PMC_IN_KERNEL(pc) ||
|
||||||
stackend = (uintptr_t) td->td_kstack + td->td_kstack_pages * PAGE_SIZE;
|
!PMC_IN_KERNEL_STACK(ra) || !PMC_IN_KERNEL_STACK(sp) ||
|
||||||
|
!PMC_IN_KERNEL_STACK(fp))
|
||||||
if (PMC_IN_TRAP_HANDLER(pc) ||
|
|
||||||
!PMC_IN_KERNEL(pc) ||
|
|
||||||
!PMC_IN_KERNEL_STACK(r, stackstart, stackend) ||
|
|
||||||
!PMC_IN_KERNEL_STACK(sp, stackstart, stackend) ||
|
|
||||||
!PMC_IN_KERNEL_STACK(fp, stackstart, stackend))
|
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
instr = *(uint32_t *) pc;
|
instr = *(uint32_t *)pc;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine whether the interrupted function was in the
|
* Determine whether the interrupted function was in the
|
||||||
@ -205,15 +199,15 @@ pmc_save_kernel_callchain(uintptr_t *cc, int nframes, struct trapframe *tf)
|
|||||||
* and the caller's address is therefore at sp[1].
|
* and the caller's address is therefore at sp[1].
|
||||||
*/
|
*/
|
||||||
sp += sizeof(uintptr_t);
|
sp += sizeof(uintptr_t);
|
||||||
if (!PMC_IN_KERNEL_STACK(sp, stackstart, stackend))
|
if (!PMC_IN_KERNEL_STACK(sp))
|
||||||
return (1);
|
return (1);
|
||||||
pc = *(uintptr_t *) sp;
|
pc = *(uintptr_t *)sp;
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Not in the function prologue or epilogue.
|
* Not in the function prologue or epilogue.
|
||||||
*/
|
*/
|
||||||
pc = *(uintptr_t *) r;
|
pc = *(uintptr_t *)ra;
|
||||||
fp = *(uintptr_t *) fp;
|
fp = *(uintptr_t *)fp;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (n = 1; n < nframes; n++) {
|
for (n = 1; n < nframes; n++) {
|
||||||
@ -222,12 +216,11 @@ pmc_save_kernel_callchain(uintptr_t *cc, int nframes, struct trapframe *tf)
|
|||||||
if (PMC_IN_TRAP_HANDLER(pc))
|
if (PMC_IN_TRAP_HANDLER(pc))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
r = fp + sizeof(uintptr_t);
|
ra = fp + sizeof(uintptr_t);
|
||||||
if (!PMC_IN_KERNEL_STACK(fp, stackstart, stackend) ||
|
if (!PMC_IN_KERNEL_STACK(fp) || !PMC_IN_KERNEL_STACK(ra))
|
||||||
!PMC_IN_KERNEL_STACK(r, stackstart, stackend))
|
|
||||||
break;
|
break;
|
||||||
pc = *(uintptr_t *) r;
|
pc = *(uintptr_t *)ra;
|
||||||
fp = *(uintptr_t *) fp;
|
fp = *(uintptr_t *)fp;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (n);
|
return (n);
|
||||||
@ -236,7 +229,6 @@ pmc_save_kernel_callchain(uintptr_t *cc, int nframes, struct trapframe *tf)
|
|||||||
/*
|
/*
|
||||||
* Machine dependent initialization for x86 class platforms.
|
* Machine dependent initialization for x86 class platforms.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct pmc_mdep *
|
struct pmc_mdep *
|
||||||
pmc_md_initialize(void)
|
pmc_md_initialize(void)
|
||||||
{
|
{
|
||||||
|
@ -121,11 +121,9 @@ struct pmc_mdep;
|
|||||||
#define PMC_TRAPFRAME_TO_USER_SP(TF) ((TF)->tf_esp)
|
#define PMC_TRAPFRAME_TO_USER_SP(TF) ((TF)->tf_esp)
|
||||||
#define PMC_TRAPFRAME_TO_KERNEL_SP(TF) ((uintptr_t) &((TF)->tf_esp))
|
#define PMC_TRAPFRAME_TO_KERNEL_SP(TF) ((uintptr_t) &((TF)->tf_esp))
|
||||||
|
|
||||||
#define PMC_IN_KERNEL_STACK(S,START,END) \
|
#define PMC_IN_KERNEL_STACK(va) kstack_contains(curthread, (va), sizeof(va))
|
||||||
((S) >= (START) && (S) < (END))
|
|
||||||
#define PMC_IN_KERNEL(va) INKERNEL(va)
|
#define PMC_IN_KERNEL(va) INKERNEL(va)
|
||||||
|
#define PMC_IN_USERSPACE(va) ((va) <= VM_MAXUSER_ADDRESS)
|
||||||
#define PMC_IN_USERSPACE(va) ((va) <= VM_MAXUSER_ADDRESS)
|
|
||||||
|
|
||||||
#define PMC_IN_TRAP_HANDLER(PC) \
|
#define PMC_IN_TRAP_HANDLER(PC) \
|
||||||
((PC) >= (uintptr_t)start_exceptions + setidt_disp && \
|
((PC) >= (uintptr_t)start_exceptions + setidt_disp && \
|
||||||
|
@ -48,12 +48,11 @@ union pmc_md_pmc {
|
|||||||
struct pmc_md_riscv_pmc pm_riscv;
|
struct pmc_md_riscv_pmc pm_riscv;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PMC_IN_KERNEL_STACK(S,START,END) \
|
#define PMC_IN_KERNEL_STACK(va) kstack_contains(curthread, (va), sizeof(va))
|
||||||
((S) >= (START) && (S) < (END))
|
#define PMC_IN_KERNEL(va) INKERNEL((va))
|
||||||
#define PMC_IN_KERNEL(va) INKERNEL((va))
|
#define PMC_IN_USERSPACE(va) ((va) <= VM_MAXUSER_ADDRESS)
|
||||||
#define PMC_IN_USERSPACE(va) ((va) <= VM_MAXUSER_ADDRESS)
|
#define PMC_TRAPFRAME_TO_PC(TF) ((TF)->tf_ra)
|
||||||
#define PMC_TRAPFRAME_TO_PC(TF) ((TF)->tf_ra)
|
#define PMC_TRAPFRAME_TO_FP(TF) (0) /* stub */
|
||||||
#define PMC_TRAPFRAME_TO_FP(TF) (0) /* stub */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prototypes
|
* Prototypes
|
||||||
|
Loading…
Reference in New Issue
Block a user