hwpmc: simplify calling convention for hwpmc interrupt handling
pmc_process_interrupt takes 5 arguments when only 3 are needed. cpu is always available in curcpu and inuserspace can always be derived from the passed trapframe. While facially a reasonable cleanup this change was motivated by the need to workaround a compiler bug. core2_intr(cpu, tf) -> pmc_process_interrupt(cpu, ring, pmc, tf, inuserspace) -> pmc_add_sample(cpu, ring, pm, tf, inuserspace) In the process of optimizing the tail call the tf pointer was getting clobbered: (kgdb) up at /storage/mmacy/devel/freebsd/sys/dev/hwpmc/hwpmc_mod.c:4709 4709 pmc_save_kernel_callchain(ps->ps_pc, (kgdb) up 1205 error = pmc_process_interrupt(cpu, PMC_HR, pm, tf, resulting in a crash in pmc_save_kernel_callchain.
This commit is contained in:
parent
dfa5753e09
commit
eb7c901995
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=334827
@ -214,7 +214,7 @@ trap(struct trapframe *frame)
|
|||||||
* the NMI was consumed by it and we can return immediately.
|
* the NMI was consumed by it and we can return immediately.
|
||||||
*/
|
*/
|
||||||
if (pmc_intr != NULL &&
|
if (pmc_intr != NULL &&
|
||||||
(*pmc_intr)(PCPU_GET(cpuid), frame) != 0)
|
(*pmc_intr)(frame) != 0)
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ pmu_intr(void *arg)
|
|||||||
/* Only call into the HWPMC framework if we know there is work. */
|
/* Only call into the HWPMC framework if we know there is work. */
|
||||||
if (r != 0 && pmc_intr) {
|
if (r != 0 && pmc_intr) {
|
||||||
tf = arg;
|
tf = arg;
|
||||||
(*pmc_intr)(PCPU_GET(cpuid), tf);
|
(*pmc_intr)(tf);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -627,14 +627,15 @@ amd_stop_pmc(int cpu, int ri)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
amd_intr(int cpu, struct trapframe *tf)
|
amd_intr(struct trapframe *tf)
|
||||||
{
|
{
|
||||||
int i, error, retval;
|
int i, error, retval, cpu;
|
||||||
uint32_t config, evsel, perfctr;
|
uint32_t config, evsel, perfctr;
|
||||||
struct pmc *pm;
|
struct pmc *pm;
|
||||||
struct amd_cpu *pac;
|
struct amd_cpu *pac;
|
||||||
pmc_value_t v;
|
pmc_value_t v;
|
||||||
|
|
||||||
|
cpu = curcpu;
|
||||||
KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
|
KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
|
||||||
("[amd,%d] out of range CPU %d", __LINE__, cpu));
|
("[amd,%d] out of range CPU %d", __LINE__, cpu));
|
||||||
|
|
||||||
@ -688,8 +689,7 @@ amd_intr(int cpu, struct trapframe *tf)
|
|||||||
wrmsr(perfctr, AMD_RELOAD_COUNT_TO_PERFCTR_VALUE(v));
|
wrmsr(perfctr, AMD_RELOAD_COUNT_TO_PERFCTR_VALUE(v));
|
||||||
|
|
||||||
/* Restart the counter if logging succeeded. */
|
/* Restart the counter if logging succeeded. */
|
||||||
error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
|
error = pmc_process_interrupt(PMC_HR, pm, tf);
|
||||||
TRAPF_USERMODE(tf));
|
|
||||||
if (error == 0)
|
if (error == 0)
|
||||||
wrmsr(evsel, config);
|
wrmsr(evsel, config);
|
||||||
}
|
}
|
||||||
|
@ -323,18 +323,19 @@ arm64_release_pmc(int cpu, int ri, struct pmc *pmc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
arm64_intr(int cpu, struct trapframe *tf)
|
arm64_intr(struct trapframe *tf)
|
||||||
{
|
{
|
||||||
struct arm64_cpu *pc;
|
struct arm64_cpu *pc;
|
||||||
int retval, ri;
|
int retval, ri;
|
||||||
struct pmc *pm;
|
struct pmc *pm;
|
||||||
int error;
|
int error;
|
||||||
int reg;
|
int reg, cpu;
|
||||||
|
|
||||||
KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
|
KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
|
||||||
("[arm64,%d] CPU %d out of range", __LINE__, cpu));
|
("[arm64,%d] CPU %d out of range", __LINE__, cpu));
|
||||||
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
cpu = curcpu;
|
||||||
pc = arm64_pcpu[cpu];
|
pc = arm64_pcpu[cpu];
|
||||||
|
|
||||||
for (ri = 0; ri < arm64_npmcs; ri++) {
|
for (ri = 0; ri < arm64_npmcs; ri++) {
|
||||||
@ -357,8 +358,7 @@ arm64_intr(int cpu, struct trapframe *tf)
|
|||||||
if (pm->pm_state != PMC_STATE_RUNNING)
|
if (pm->pm_state != PMC_STATE_RUNNING)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
|
error = pmc_process_interrupt(PMC_HR, pm, tf);
|
||||||
TRAPF_USERMODE(tf));
|
|
||||||
if (error)
|
if (error)
|
||||||
arm64_stop_pmc(cpu, ri);
|
arm64_stop_pmc(cpu, ri);
|
||||||
|
|
||||||
|
@ -307,18 +307,19 @@ armv7_release_pmc(int cpu, int ri, struct pmc *pmc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
armv7_intr(int cpu, struct trapframe *tf)
|
armv7_intr(struct trapframe *tf)
|
||||||
{
|
{
|
||||||
struct armv7_cpu *pc;
|
struct armv7_cpu *pc;
|
||||||
int retval, ri;
|
int retval, ri;
|
||||||
struct pmc *pm;
|
struct pmc *pm;
|
||||||
int error;
|
int error;
|
||||||
int reg;
|
int reg, cpu;
|
||||||
|
|
||||||
KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
|
KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
|
||||||
("[armv7,%d] CPU %d out of range", __LINE__, cpu));
|
("[armv7,%d] CPU %d out of range", __LINE__, cpu));
|
||||||
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
cpu = curcpu;
|
||||||
pc = armv7_pcpu[cpu];
|
pc = armv7_pcpu[cpu];
|
||||||
|
|
||||||
for (ri = 0; ri < armv7_npmcs; ri++) {
|
for (ri = 0; ri < armv7_npmcs; ri++) {
|
||||||
@ -348,8 +349,7 @@ armv7_intr(int cpu, struct trapframe *tf)
|
|||||||
if (pm->pm_state != PMC_STATE_RUNNING)
|
if (pm->pm_state != PMC_STATE_RUNNING)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
|
error = pmc_process_interrupt(PMC_HR, pm, tf);
|
||||||
TRAPF_USERMODE(tf));
|
|
||||||
if (error)
|
if (error)
|
||||||
armv7_stop_pmc(cpu, ri);
|
armv7_stop_pmc(cpu, ri);
|
||||||
|
|
||||||
|
@ -1056,7 +1056,7 @@ iap_initialize(struct pmc_mdep *md, int maxcpu, int npmc, int pmcwidth,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
core_intr(int cpu, struct trapframe *tf)
|
core_intr(struct trapframe *tf)
|
||||||
{
|
{
|
||||||
pmc_value_t v;
|
pmc_value_t v;
|
||||||
struct pmc *pm;
|
struct pmc *pm;
|
||||||
@ -1064,11 +1064,11 @@ core_intr(int cpu, struct trapframe *tf)
|
|||||||
int error, found_interrupt, ri;
|
int error, found_interrupt, ri;
|
||||||
uint64_t msr;
|
uint64_t msr;
|
||||||
|
|
||||||
PMCDBG3(MDP,INT, 1, "cpu=%d tf=0x%p um=%d", cpu, (void *) tf,
|
PMCDBG3(MDP,INT, 1, "cpu=%d tf=0x%p um=%d", curcpu, (void *) tf,
|
||||||
TRAPF_USERMODE(tf));
|
TRAPF_USERMODE(tf));
|
||||||
|
|
||||||
found_interrupt = 0;
|
found_interrupt = 0;
|
||||||
cc = core_pcpu[cpu];
|
cc = core_pcpu[curcpu];
|
||||||
|
|
||||||
for (ri = 0; ri < core_iap_npmc; ri++) {
|
for (ri = 0; ri < core_iap_npmc; ri++) {
|
||||||
|
|
||||||
@ -1084,8 +1084,7 @@ core_intr(int cpu, struct trapframe *tf)
|
|||||||
if (pm->pm_state != PMC_STATE_RUNNING)
|
if (pm->pm_state != PMC_STATE_RUNNING)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
|
error = pmc_process_interrupt(PMC_HR, pm, tf);
|
||||||
TRAPF_USERMODE(tf));
|
|
||||||
|
|
||||||
v = pm->pm_sc.pm_reloadcount;
|
v = pm->pm_sc.pm_reloadcount;
|
||||||
v = iap_reload_count_to_perfctr_value(v);
|
v = iap_reload_count_to_perfctr_value(v);
|
||||||
@ -1117,7 +1116,7 @@ core_intr(int cpu, struct trapframe *tf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
core2_intr(int cpu, struct trapframe *tf)
|
core2_intr(struct trapframe *tf)
|
||||||
{
|
{
|
||||||
int error, found_interrupt, n;
|
int error, found_interrupt, n;
|
||||||
uint64_t flag, intrstatus, intrenable, msr;
|
uint64_t flag, intrstatus, intrenable, msr;
|
||||||
@ -1141,7 +1140,7 @@ core2_intr(int cpu, struct trapframe *tf)
|
|||||||
(uintmax_t) intrstatus);
|
(uintmax_t) intrstatus);
|
||||||
|
|
||||||
found_interrupt = 0;
|
found_interrupt = 0;
|
||||||
cc = core_pcpu[cpu];
|
cc = core_pcpu[curcpu];
|
||||||
|
|
||||||
KASSERT(cc != NULL, ("[core,%d] null pcpu", __LINE__));
|
KASSERT(cc != NULL, ("[core,%d] null pcpu", __LINE__));
|
||||||
|
|
||||||
@ -1173,8 +1172,7 @@ core2_intr(int cpu, struct trapframe *tf)
|
|||||||
!PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
|
!PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
|
error = pmc_process_interrupt(PMC_HR, pm, tf);
|
||||||
TRAPF_USERMODE(tf));
|
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
intrenable &= ~flag;
|
intrenable &= ~flag;
|
||||||
@ -1184,7 +1182,7 @@ core2_intr(int cpu, struct trapframe *tf)
|
|||||||
/* Reload sampling count. */
|
/* Reload sampling count. */
|
||||||
wrmsr(IAF_CTR0 + n, v);
|
wrmsr(IAF_CTR0 + n, v);
|
||||||
|
|
||||||
PMCDBG4(MDP,INT, 1, "iaf-intr cpu=%d error=%d v=%jx(%jx)", cpu,
|
PMCDBG4(MDP,INT, 1, "iaf-intr cpu=%d error=%d v=%jx(%jx)", curcpu,
|
||||||
error, (uintmax_t) v, (uintmax_t) rdpmc(IAF_RI_TO_MSR(n)));
|
error, (uintmax_t) v, (uintmax_t) rdpmc(IAF_RI_TO_MSR(n)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1202,8 +1200,7 @@ core2_intr(int cpu, struct trapframe *tf)
|
|||||||
!PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
|
!PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
|
error = pmc_process_interrupt(PMC_HR, pm, tf);
|
||||||
TRAPF_USERMODE(tf));
|
|
||||||
if (error)
|
if (error)
|
||||||
intrenable &= ~flag;
|
intrenable &= ~flag;
|
||||||
|
|
||||||
|
@ -289,8 +289,7 @@ mips_pmc_intr(int cpu, struct trapframe *tf)
|
|||||||
retval = 1;
|
retval = 1;
|
||||||
if (pm->pm_state != PMC_STATE_RUNNING)
|
if (pm->pm_state != PMC_STATE_RUNNING)
|
||||||
continue;
|
continue;
|
||||||
error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
|
error = pmc_process_interrupt(PMC_HR, pm, tf);
|
||||||
TRAPF_USERMODE(tf));
|
|
||||||
if (error) {
|
if (error) {
|
||||||
/* Clear/disable the relevant counter */
|
/* Clear/disable the relevant counter */
|
||||||
if (ri == 0)
|
if (ri == 0)
|
||||||
|
@ -207,8 +207,7 @@ static int pmc_debugflags_parse(char *newstr, char *fence);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int load(struct module *module, int cmd, void *arg);
|
static int load(struct module *module, int cmd, void *arg);
|
||||||
static int pmc_add_sample(int cpu, int ring, struct pmc *pm,
|
static int pmc_add_sample(int ring, struct pmc *pm, struct trapframe *tf);
|
||||||
struct trapframe *tf, int inuserspace);
|
|
||||||
static void pmc_add_thread_descriptors_from_proc(struct proc *p,
|
static void pmc_add_thread_descriptors_from_proc(struct proc *p,
|
||||||
struct pmc_process *pp);
|
struct pmc_process *pp);
|
||||||
static int pmc_attach_process(struct proc *p, struct pmc *pm);
|
static int pmc_attach_process(struct proc *p, struct pmc *pm);
|
||||||
@ -4640,10 +4639,9 @@ pmc_post_callchain_callback(void)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pmc_add_sample(int cpu, int ring, struct pmc *pm, struct trapframe *tf,
|
pmc_add_sample(int ring, struct pmc *pm, struct trapframe *tf)
|
||||||
int inuserspace)
|
|
||||||
{
|
{
|
||||||
int error, callchaindepth;
|
int error, cpu, callchaindepth, inuserspace;
|
||||||
struct thread *td;
|
struct thread *td;
|
||||||
struct pmc_sample *ps;
|
struct pmc_sample *ps;
|
||||||
struct pmc_samplebuffer *psb;
|
struct pmc_samplebuffer *psb;
|
||||||
@ -4653,8 +4651,9 @@ pmc_add_sample(int cpu, int ring, struct pmc *pm, struct trapframe *tf,
|
|||||||
/*
|
/*
|
||||||
* Allocate space for a sample buffer.
|
* Allocate space for a sample buffer.
|
||||||
*/
|
*/
|
||||||
|
cpu = curcpu;
|
||||||
psb = pmc_pcpu[cpu]->pc_sb[ring];
|
psb = pmc_pcpu[cpu]->pc_sb[ring];
|
||||||
|
inuserspace = TRAPF_USERMODE(tf);
|
||||||
ps = psb->ps_write;
|
ps = psb->ps_write;
|
||||||
if (ps->ps_nsamples == PMC_SAMPLE_INUSE) {
|
if (ps->ps_nsamples == PMC_SAMPLE_INUSE) {
|
||||||
counter_u64_add(ps->ps_pmc->pm_runcount, -1);
|
counter_u64_add(ps->ps_pmc->pm_runcount, -1);
|
||||||
@ -4743,19 +4742,18 @@ pmc_add_sample(int cpu, int ring, struct pmc *pm, struct trapframe *tf,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
pmc_process_interrupt(int cpu, int ring, struct pmc *pm, struct trapframe *tf,
|
pmc_process_interrupt(int ring, struct pmc *pm, struct trapframe *tf)
|
||||||
int inuserspace)
|
|
||||||
{
|
{
|
||||||
struct thread *td;
|
struct thread *td;
|
||||||
|
|
||||||
td = curthread;
|
td = curthread;
|
||||||
if ((pm->pm_flags & PMC_F_USERCALLCHAIN) &&
|
if ((pm->pm_flags & PMC_F_USERCALLCHAIN) &&
|
||||||
(td->td_proc->p_flag & P_KPROC) == 0 &&
|
(td->td_proc->p_flag & P_KPROC) == 0 &&
|
||||||
!inuserspace) {
|
!TRAPF_USERMODE(tf)) {
|
||||||
atomic_add_int(&curthread->td_pmcpend, 1);
|
atomic_add_int(&curthread->td_pmcpend, 1);
|
||||||
return (pmc_add_sample(cpu, PMC_UR, pm, tf, 0));
|
return (pmc_add_sample(PMC_UR, pm, tf));
|
||||||
}
|
}
|
||||||
return (pmc_add_sample(cpu, ring, pm, tf, inuserspace));
|
return (pmc_add_sample(ring, pm, tf));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -702,8 +702,7 @@ mpc7xxx_intr(int cpu, struct trapframe *tf)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Stop the counter if logging fails. */
|
/* Stop the counter if logging fails. */
|
||||||
error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
|
error = pmc_process_interrupt(PMC_HR, pm, tf);
|
||||||
TRAPF_USERMODE(tf));
|
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
mpc7xxx_stop_pmc(cpu, i);
|
mpc7xxx_stop_pmc(cpu, i);
|
||||||
|
|
||||||
|
@ -519,8 +519,7 @@ ppc970_intr(int cpu, struct trapframe *tf)
|
|||||||
if (pm->pm_state != PMC_STATE_RUNNING)
|
if (pm->pm_state != PMC_STATE_RUNNING)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
|
error = pmc_process_interrupt(PMC_HR, pm, tf);
|
||||||
TRAPF_USERMODE(tf));
|
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
ppc970_stop_pmc(cpu, i);
|
ppc970_stop_pmc(cpu, i);
|
||||||
|
|
||||||
|
@ -425,8 +425,7 @@ pmc_soft_intr(struct pmckern_soft *ks)
|
|||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
user_mode = TRAPF_USERMODE(ks->pm_tf);
|
user_mode = TRAPF_USERMODE(ks->pm_tf);
|
||||||
error = pmc_process_interrupt(ks->pm_cpu, PMC_SR, pm,
|
error = pmc_process_interrupt(PMC_SR, pm, ks->pm_tf);
|
||||||
ks->pm_tf, user_mode);
|
|
||||||
if (error) {
|
if (error) {
|
||||||
soft_stop_pmc(ks->pm_cpu, ri);
|
soft_stop_pmc(ks->pm_cpu, ri);
|
||||||
continue;
|
continue;
|
||||||
|
@ -248,7 +248,7 @@ trap(struct trapframe *frame)
|
|||||||
* return immediately.
|
* return immediately.
|
||||||
*/
|
*/
|
||||||
if (pmc_intr != NULL &&
|
if (pmc_intr != NULL &&
|
||||||
(*pmc_intr)(PCPU_GET(cpuid), frame) != 0)
|
(*pmc_intr)(frame) != 0)
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ const int pmc_kernel_version = PMC_KERNEL_VERSION;
|
|||||||
int __read_mostly (*pmc_hook)(struct thread *td, int function, void *arg) = NULL;
|
int __read_mostly (*pmc_hook)(struct thread *td, int function, void *arg) = NULL;
|
||||||
|
|
||||||
/* Interrupt handler */
|
/* Interrupt handler */
|
||||||
int __read_mostly (*pmc_intr)(int cpu, struct trapframe *tf) = NULL;
|
int __read_mostly (*pmc_intr)(struct trapframe *tf) = NULL;
|
||||||
|
|
||||||
DPCPU_DEFINE(uint8_t, pmc_sampled);
|
DPCPU_DEFINE(uint8_t, pmc_sampled);
|
||||||
|
|
||||||
|
@ -388,7 +388,7 @@ apb_filter(void *arg)
|
|||||||
tf = td->td_intr_frame;
|
tf = td->td_intr_frame;
|
||||||
|
|
||||||
if (pmc_intr)
|
if (pmc_intr)
|
||||||
(*pmc_intr)(PCPU_GET(cpuid), tf);
|
(*pmc_intr)(PCPU_GET(tf);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* Ignore timer interrupts */
|
/* Ignore timer interrupts */
|
||||||
|
@ -111,7 +111,7 @@ octeon_pmc_intr(void *arg)
|
|||||||
struct trapframe *tf = PCPU_GET(curthread)->td_intr_frame;
|
struct trapframe *tf = PCPU_GET(curthread)->td_intr_frame;
|
||||||
|
|
||||||
if (pmc_intr)
|
if (pmc_intr)
|
||||||
(*pmc_intr)(PCPU_GET(cpuid), tf);
|
(*pmc_intr)(PCPU_GET(tf);
|
||||||
|
|
||||||
return (FILTER_HANDLED);
|
return (FILTER_HANDLED);
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,7 @@ powerpc_interrupt(struct trapframe *framep)
|
|||||||
case EXC_PERF:
|
case EXC_PERF:
|
||||||
critical_enter();
|
critical_enter();
|
||||||
KASSERT(pmc_intr != NULL, ("Performance exception, but no handler!"));
|
KASSERT(pmc_intr != NULL, ("Performance exception, but no handler!"));
|
||||||
(*pmc_intr)(PCPU_GET(cpuid), framep);
|
(*pmc_intr)(framep);
|
||||||
if (pmc_hook && (PCPU_GET(curthread)->td_pflags & TDP_CALLCHAIN))
|
if (pmc_hook && (PCPU_GET(curthread)->td_pflags & TDP_CALLCHAIN))
|
||||||
pmc_hook(PCPU_GET(curthread), PMC_FN_USER_CALLCHAIN, framep);
|
pmc_hook(PCPU_GET(curthread), PMC_FN_USER_CALLCHAIN, framep);
|
||||||
critical_exit();
|
critical_exit();
|
||||||
|
@ -61,7 +61,7 @@
|
|||||||
*
|
*
|
||||||
* The patch version is incremented for every bug fix.
|
* The patch version is incremented for every bug fix.
|
||||||
*/
|
*/
|
||||||
#define PMC_VERSION_MAJOR 0x08
|
#define PMC_VERSION_MAJOR 0x09
|
||||||
#define PMC_VERSION_MINOR 0x03
|
#define PMC_VERSION_MINOR 0x03
|
||||||
#define PMC_VERSION_PATCH 0x0000
|
#define PMC_VERSION_PATCH 0x0000
|
||||||
|
|
||||||
@ -1053,7 +1053,7 @@ struct pmc_mdep {
|
|||||||
int (*pmd_switch_out)(struct pmc_cpu *_p, struct pmc_process *_pp);
|
int (*pmd_switch_out)(struct pmc_cpu *_p, struct pmc_process *_pp);
|
||||||
|
|
||||||
/* handle a PMC interrupt */
|
/* handle a PMC interrupt */
|
||||||
int (*pmd_intr)(int _cpu, struct trapframe *_tf);
|
int (*pmd_intr)(struct trapframe *_tf);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PMC class dependent information.
|
* PMC class dependent information.
|
||||||
@ -1209,8 +1209,7 @@ MALLOC_DECLARE(M_PMC);
|
|||||||
struct pmc_mdep *pmc_md_initialize(void); /* MD init function */
|
struct pmc_mdep *pmc_md_initialize(void); /* MD init function */
|
||||||
void pmc_md_finalize(struct pmc_mdep *_md); /* MD fini function */
|
void pmc_md_finalize(struct pmc_mdep *_md); /* MD fini function */
|
||||||
int pmc_getrowdisp(int _ri);
|
int pmc_getrowdisp(int _ri);
|
||||||
int pmc_process_interrupt(int _cpu, int _ring, struct pmc *_pm,
|
int pmc_process_interrupt(int _ring, struct pmc *_pm, struct trapframe *_tf);
|
||||||
struct trapframe *_tf, int _inuserspace);
|
|
||||||
int pmc_save_kernel_callchain(uintptr_t *_cc, int _maxsamples,
|
int pmc_save_kernel_callchain(uintptr_t *_cc, int _maxsamples,
|
||||||
struct trapframe *_tf);
|
struct trapframe *_tf);
|
||||||
int pmc_save_user_callchain(uintptr_t *_cc, int _maxsamples,
|
int pmc_save_user_callchain(uintptr_t *_cc, int _maxsamples,
|
||||||
|
@ -176,7 +176,7 @@ struct pmc_domain_buffer_header {
|
|||||||
|
|
||||||
/* hook */
|
/* hook */
|
||||||
extern int (*pmc_hook)(struct thread *_td, int _function, void *_arg);
|
extern int (*pmc_hook)(struct thread *_td, int _function, void *_arg);
|
||||||
extern int (*pmc_intr)(int _cpu, struct trapframe *_frame);
|
extern int (*pmc_intr)(struct trapframe *_frame);
|
||||||
|
|
||||||
/* SX lock protecting the hook */
|
/* SX lock protecting the hook */
|
||||||
extern struct sx pmc_sx;
|
extern struct sx pmc_sx;
|
||||||
|
Loading…
Reference in New Issue
Block a user