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,10 +109,8 @@ union pmc_md_pmc {
|
||||
((PC) >= (uintptr_t) start_exceptions && \
|
||||
(PC) < (uintptr_t) end_exceptions)
|
||||
|
||||
#define PMC_IN_KERNEL_STACK(S,START,END) \
|
||||
((S) >= (START) && (S) < (END))
|
||||
#define PMC_IN_KERNEL_STACK(va) kstack_contains(curthread, (va), sizeof(va))
|
||||
#define PMC_IN_KERNEL(va) INKERNEL(va)
|
||||
|
||||
#define PMC_IN_USERSPACE(va) ((va) <= VM_MAXUSER_ADDRESS)
|
||||
|
||||
/* Build a fake kernel trapframe from current instruction pointer. */
|
||||
|
@ -52,10 +52,8 @@ union pmc_md_pmc {
|
||||
struct pmc_md_armv7_pmc pm_armv7;
|
||||
};
|
||||
|
||||
#define PMC_IN_KERNEL_STACK(S,START,END) \
|
||||
((S) >= (START) && (S) < (END))
|
||||
#define PMC_IN_KERNEL_STACK(va) kstack_contains(curthread, (va), sizeof(va))
|
||||
#define PMC_IN_KERNEL(va) INKERNEL((va))
|
||||
|
||||
#define PMC_IN_USERSPACE(va) ((va) <= VM_MAXUSER_ADDRESS)
|
||||
|
||||
#define PMC_TRAPFRAME_TO_PC(TF) ((TF)->tf_pc)
|
||||
|
@ -66,8 +66,7 @@ union pmc_md_pmc {
|
||||
struct pmc_md_dmc620_pmc pm_dmc620;
|
||||
};
|
||||
|
||||
#define PMC_IN_KERNEL_STACK(S,START,END) \
|
||||
((S) >= (START) && (S) < (END))
|
||||
#define PMC_IN_KERNEL_STACK(va) kstack_contains(curthread, (va), sizeof(va))
|
||||
#define PMC_IN_KERNEL(va) INKERNEL((va))
|
||||
#define PMC_IN_USERSPACE(va) ((va) <= VM_MAXUSER_ADDRESS)
|
||||
#define PMC_TRAPFRAME_TO_PC(TF) ((TF)->tf_elr)
|
||||
|
@ -31,18 +31,17 @@
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/pmc.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/pmc.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/pmap.h>
|
||||
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/md_var.h>
|
||||
#include <machine/pmc_mdep.h>
|
||||
#include <machine/stack.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <machine/vmparam.h>
|
||||
|
||||
/* XXX: Userland code compiled with gcc will need an heuristic
|
||||
* to be correctly detected.
|
||||
@ -78,45 +77,39 @@ int
|
||||
pmc_save_kernel_callchain(uintptr_t *cc, int maxsamples,
|
||||
struct trapframe *tf)
|
||||
{
|
||||
uintptr_t pc, r, stackstart, stackend, fp;
|
||||
struct thread *td;
|
||||
uintptr_t pc, ra, fp;
|
||||
int count;
|
||||
|
||||
KASSERT(TRAPF_USERMODE(tf) == 0,("[arm,%d] not a kernel backtrace",
|
||||
__LINE__));
|
||||
|
||||
td = curthread;
|
||||
pc = PMC_TRAPFRAME_TO_PC(tf);
|
||||
*cc++ = pc;
|
||||
|
||||
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))
|
||||
if (!PMC_IN_KERNEL(pc) || !PMC_IN_KERNEL_STACK(fp))
|
||||
return (1);
|
||||
|
||||
for (count = 1; count < maxsamples; count++) {
|
||||
/* Use saved lr as pc. */
|
||||
r = fp + PC_OFF * sizeof(uintptr_t);
|
||||
if (!PMC_IN_KERNEL_STACK(r, stackstart, stackend))
|
||||
ra = fp + PC_OFF * sizeof(uintptr_t);
|
||||
if (!PMC_IN_KERNEL_STACK(ra))
|
||||
break;
|
||||
pc = *(uintptr_t *)r;
|
||||
pc = *(uintptr_t *)ra;
|
||||
if (!PMC_IN_KERNEL(pc))
|
||||
break;
|
||||
|
||||
*cc++ = pc;
|
||||
|
||||
/* Switch to next frame up */
|
||||
r = fp + FP_OFF * sizeof(uintptr_t);
|
||||
if (!PMC_IN_KERNEL_STACK(r, stackstart, stackend))
|
||||
ra = fp + FP_OFF * sizeof(uintptr_t);
|
||||
if (!PMC_IN_KERNEL_STACK(ra))
|
||||
break;
|
||||
fp = *(uintptr_t *)r;
|
||||
if (!PMC_IN_KERNEL_STACK(fp, stackstart, stackend))
|
||||
fp = *(uintptr_t *)ra;
|
||||
if (!PMC_IN_KERNEL_STACK(fp))
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -31,18 +31,17 @@
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/pmc.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/pmc.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/pmap.h>
|
||||
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/md_var.h>
|
||||
#include <machine/pmc_mdep.h>
|
||||
#include <machine/stack.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <machine/vmparam.h>
|
||||
|
||||
struct pmc_mdep *
|
||||
pmc_md_initialize(void)
|
||||
@ -59,30 +58,22 @@ pmc_md_finalize(struct pmc_mdep *md)
|
||||
}
|
||||
|
||||
int
|
||||
pmc_save_kernel_callchain(uintptr_t *cc, int maxsamples,
|
||||
struct trapframe *tf)
|
||||
pmc_save_kernel_callchain(uintptr_t *cc, int maxsamples, struct trapframe *tf)
|
||||
{
|
||||
struct unwind_state frame;
|
||||
uintptr_t stackstart, stackend;
|
||||
struct thread *td;
|
||||
int count;
|
||||
|
||||
KASSERT(TRAPF_USERMODE(tf) == 0,("[arm64,%d] not a kernel backtrace",
|
||||
__LINE__));
|
||||
|
||||
td = curthread;
|
||||
frame.pc = PMC_TRAPFRAME_TO_PC(tf);
|
||||
*cc++ = frame.pc;
|
||||
|
||||
if (maxsamples <= 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);
|
||||
|
||||
if (!PMC_IN_KERNEL(frame.pc) ||
|
||||
!PMC_IN_KERNEL_STACK(frame.fp, stackstart, stackend))
|
||||
if (!PMC_IN_KERNEL(frame.pc) || !PMC_IN_KERNEL_STACK(frame.fp))
|
||||
return (1);
|
||||
|
||||
for (count = 1; count < maxsamples; count++) {
|
||||
|
@ -34,21 +34,22 @@
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.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/cputypes.h>
|
||||
#include <machine/intr_machdep.h>
|
||||
#include <x86/apicvar.h>
|
||||
#include <machine/pmc_mdep.h>
|
||||
#include <machine/intr_machdep.h> /* For x86/apicvar.h */
|
||||
#include <machine/md_var.h>
|
||||
#include <machine/pmc_mdep.h>
|
||||
#include <machine/stack.h>
|
||||
#include <machine/vmparam.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <x86/apicvar.h>
|
||||
|
||||
#include "hwpmc_soft.h"
|
||||
|
||||
@ -155,36 +156,29 @@ pmc_save_user_callchain(uintptr_t *cc, int nframes, struct trapframe *tf)
|
||||
int __nosanitizeaddress __nosanitizememory
|
||||
pmc_save_kernel_callchain(uintptr_t *cc, int nframes, struct trapframe *tf)
|
||||
{
|
||||
int n;
|
||||
uintptr_t fp, pc, ra, sp;
|
||||
uint32_t instr;
|
||||
uintptr_t fp, pc, r, sp, stackstart, stackend;
|
||||
struct thread *td;
|
||||
int n;
|
||||
|
||||
KASSERT(TRAPF_USERMODE(tf) == 0,("[x86,%d] not a kernel backtrace",
|
||||
__LINE__));
|
||||
|
||||
td = curthread;
|
||||
pc = PMC_TRAPFRAME_TO_PC(tf);
|
||||
fp = PMC_TRAPFRAME_TO_FP(tf);
|
||||
sp = PMC_TRAPFRAME_TO_KERNEL_SP(tf);
|
||||
|
||||
*cc++ = pc;
|
||||
r = fp + sizeof(uintptr_t); /* points to return address */
|
||||
ra = fp + sizeof(uintptr_t); /* points to return address */
|
||||
|
||||
if (nframes <= 1)
|
||||
return (1);
|
||||
|
||||
stackstart = (uintptr_t) td->td_kstack;
|
||||
stackend = (uintptr_t) td->td_kstack + td->td_kstack_pages * PAGE_SIZE;
|
||||
|
||||
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))
|
||||
if (PMC_IN_TRAP_HANDLER(pc) || !PMC_IN_KERNEL(pc) ||
|
||||
!PMC_IN_KERNEL_STACK(ra) || !PMC_IN_KERNEL_STACK(sp) ||
|
||||
!PMC_IN_KERNEL_STACK(fp))
|
||||
return (1);
|
||||
|
||||
instr = *(uint32_t *) pc;
|
||||
instr = *(uint32_t *)pc;
|
||||
|
||||
/*
|
||||
* 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].
|
||||
*/
|
||||
sp += sizeof(uintptr_t);
|
||||
if (!PMC_IN_KERNEL_STACK(sp, stackstart, stackend))
|
||||
if (!PMC_IN_KERNEL_STACK(sp))
|
||||
return (1);
|
||||
pc = *(uintptr_t *) sp;
|
||||
pc = *(uintptr_t *)sp;
|
||||
} else {
|
||||
/*
|
||||
* Not in the function prologue or epilogue.
|
||||
*/
|
||||
pc = *(uintptr_t *) r;
|
||||
fp = *(uintptr_t *) fp;
|
||||
pc = *(uintptr_t *)ra;
|
||||
fp = *(uintptr_t *)fp;
|
||||
}
|
||||
|
||||
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))
|
||||
break;
|
||||
|
||||
r = fp + sizeof(uintptr_t);
|
||||
if (!PMC_IN_KERNEL_STACK(fp, stackstart, stackend) ||
|
||||
!PMC_IN_KERNEL_STACK(r, stackstart, stackend))
|
||||
ra = fp + sizeof(uintptr_t);
|
||||
if (!PMC_IN_KERNEL_STACK(fp) || !PMC_IN_KERNEL_STACK(ra))
|
||||
break;
|
||||
pc = *(uintptr_t *) r;
|
||||
fp = *(uintptr_t *) fp;
|
||||
pc = *(uintptr_t *)ra;
|
||||
fp = *(uintptr_t *)fp;
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
struct pmc_mdep *
|
||||
pmc_md_initialize(void)
|
||||
{
|
||||
|
@ -121,10 +121,8 @@ struct pmc_mdep;
|
||||
#define PMC_TRAPFRAME_TO_USER_SP(TF) ((TF)->tf_esp)
|
||||
#define PMC_TRAPFRAME_TO_KERNEL_SP(TF) ((uintptr_t) &((TF)->tf_esp))
|
||||
|
||||
#define PMC_IN_KERNEL_STACK(S,START,END) \
|
||||
((S) >= (START) && (S) < (END))
|
||||
#define PMC_IN_KERNEL_STACK(va) kstack_contains(curthread, (va), sizeof(va))
|
||||
#define PMC_IN_KERNEL(va) INKERNEL(va)
|
||||
|
||||
#define PMC_IN_USERSPACE(va) ((va) <= VM_MAXUSER_ADDRESS)
|
||||
|
||||
#define PMC_IN_TRAP_HANDLER(PC) \
|
||||
|
@ -48,8 +48,7 @@ union pmc_md_pmc {
|
||||
struct pmc_md_riscv_pmc pm_riscv;
|
||||
};
|
||||
|
||||
#define PMC_IN_KERNEL_STACK(S,START,END) \
|
||||
((S) >= (START) && (S) < (END))
|
||||
#define PMC_IN_KERNEL_STACK(va) kstack_contains(curthread, (va), sizeof(va))
|
||||
#define PMC_IN_KERNEL(va) INKERNEL((va))
|
||||
#define PMC_IN_USERSPACE(va) ((va) <= VM_MAXUSER_ADDRESS)
|
||||
#define PMC_TRAPFRAME_TO_PC(TF) ((TF)->tf_ra)
|
||||
|
Loading…
Reference in New Issue
Block a user