]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/hwpmc/hwpmc_powerpc.c
ssh: update to OpenSSH v9.0p1
[FreeBSD/FreeBSD.git] / sys / dev / hwpmc / hwpmc_powerpc.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2011,2013 Justin Hibbits
5  * Copyright (c) 2005, Joseph Koshy
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include <sys/param.h>
35 #include <sys/pmc.h>
36 #include <sys/pmckern.h>
37 #include <sys/sysent.h>
38 #include <sys/syslog.h>
39 #include <sys/systm.h>
40
41 #include <machine/pmc_mdep.h>
42 #include <machine/spr.h>
43 #include <machine/pte.h>
44 #include <machine/sr.h>
45 #include <machine/cpu.h>
46 #include <machine/stack.h>
47
48 #include "hwpmc_powerpc.h"
49
50 #ifdef __powerpc64__
51 #define OFFSET 4 /* Account for the TOC reload slot */
52 #else
53 #define OFFSET 0
54 #endif
55
56 struct powerpc_cpu **powerpc_pcpu;
57 struct pmc_ppc_event *ppc_event_codes;
58 size_t ppc_event_codes_size;
59 int ppc_event_first;
60 int ppc_event_last;
61 int ppc_max_pmcs;
62 enum pmc_class ppc_class;
63
64 void (*powerpc_set_pmc)(int cpu, int ri, int config);
65 pmc_value_t (*powerpc_pmcn_read)(unsigned int pmc);
66 void (*powerpc_pmcn_write)(unsigned int pmc, uint32_t val);
67 void (*powerpc_resume_pmc)(bool ie);
68
69
70 int
71 pmc_save_kernel_callchain(uintptr_t *cc, int maxsamples,
72     struct trapframe *tf)
73 {
74         uintptr_t *osp, *sp;
75         uintptr_t pc;
76         int frames = 0;
77
78         cc[frames++] = PMC_TRAPFRAME_TO_PC(tf);
79         sp = (uintptr_t *)PMC_TRAPFRAME_TO_FP(tf);
80         osp = (uintptr_t *)PAGE_SIZE;
81
82         for (; frames < maxsamples; frames++) {
83                 if (sp <= osp)
84                         break;
85             #ifdef __powerpc64__
86                 pc = sp[2];
87             #else
88                 pc = sp[1];
89             #endif
90                 if ((pc & 3) || (pc < 0x100))
91                         break;
92
93                 /*
94                  * trapexit() and asttrapexit() are sentinels
95                  * for kernel stack tracing.
96                  * */
97                 if (pc + OFFSET == (uintptr_t) &trapexit ||
98                     pc + OFFSET == (uintptr_t) &asttrapexit)
99                         break;
100
101                 cc[frames] = pc;
102                 osp = sp;
103                 sp = (uintptr_t *)*sp;
104         }
105         return (frames);
106 }
107
108 static int
109 powerpc_switch_in(struct pmc_cpu *pc, struct pmc_process *pp)
110 {
111
112         return (0);
113 }
114
115 static int
116 powerpc_switch_out(struct pmc_cpu *pc, struct pmc_process *pp)
117 {
118
119         return (0);
120 }
121
122 int
123 powerpc_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc)
124 {
125         int error;
126         struct pmc_hw *phw;
127         char powerpc_name[PMC_NAME_MAX];
128
129         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
130             ("[powerpc,%d], illegal CPU %d", __LINE__, cpu));
131
132         phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri];
133         snprintf(powerpc_name, sizeof(powerpc_name), "POWERPC-%d", ri);
134         if ((error = copystr(powerpc_name, pi->pm_name, PMC_NAME_MAX,
135             NULL)) != 0)
136                 return error;
137         pi->pm_class = powerpc_pcpu[cpu]->pc_class;
138         if (phw->phw_state & PMC_PHW_FLAG_IS_ENABLED) {
139                 pi->pm_enabled = TRUE;
140                 *ppmc          = phw->phw_pmc;
141         } else {
142                 pi->pm_enabled = FALSE;
143                 *ppmc          = NULL;
144         }
145
146         return (0);
147 }
148
149 int
150 powerpc_get_config(int cpu, int ri, struct pmc **ppm)
151 {
152
153         *ppm = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc;
154
155         return (0);
156 }
157
158 int
159 powerpc_pcpu_init(struct pmc_mdep *md, int cpu)
160 {
161         struct pmc_cpu *pc;
162         struct powerpc_cpu *pac;
163         struct pmc_hw  *phw;
164         int first_ri, i;
165
166         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
167             ("[powerpc,%d] wrong cpu number %d", __LINE__, cpu));
168         PMCDBG1(MDP,INI,1,"powerpc-init cpu=%d", cpu);
169
170         powerpc_pcpu[cpu] = pac = malloc(sizeof(struct powerpc_cpu), M_PMC,
171             M_WAITOK|M_ZERO);
172         pac->pc_ppcpmcs = malloc(sizeof(struct pmc_hw) * ppc_max_pmcs,
173             M_PMC, M_WAITOK|M_ZERO);
174         pac->pc_class =
175             md->pmd_classdep[PMC_MDEP_CLASS_INDEX_POWERPC].pcd_class;
176
177         pc = pmc_pcpu[cpu];
178         first_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_POWERPC].pcd_ri;
179         KASSERT(pc != NULL, ("[powerpc,%d] NULL per-cpu pointer", __LINE__));
180
181         for (i = 0, phw = pac->pc_ppcpmcs; i < ppc_max_pmcs; i++, phw++) {
182                 phw->phw_state = PMC_PHW_FLAG_IS_ENABLED |
183                     PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(i);
184                 phw->phw_pmc = NULL;
185                 pc->pc_hwpmcs[i + first_ri] = phw;
186         }
187
188         return (0);
189 }
190
191 int
192 powerpc_pcpu_fini(struct pmc_mdep *md, int cpu)
193 {
194         PMCDBG1(MDP,INI,1,"powerpc-fini cpu=%d", cpu);
195
196         free(powerpc_pcpu[cpu]->pc_ppcpmcs, M_PMC);
197         free(powerpc_pcpu[cpu], M_PMC);
198
199         return (0);
200 }
201
202 int
203 powerpc_allocate_pmc(int cpu, int ri, struct pmc *pm,
204     const struct pmc_op_pmcallocate *a)
205 {
206         enum pmc_event pe;
207         uint32_t caps, config = 0, counter = 0;
208         int i;
209
210         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
211             ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu));
212         KASSERT(ri >= 0 && ri < ppc_max_pmcs,
213             ("[powerpc,%d] illegal row index %d", __LINE__, ri));
214
215         if (a->pm_class != ppc_class)
216                 return (EINVAL);
217
218         caps = a->pm_caps;
219
220         pe = a->pm_ev;
221
222         if (pe < ppc_event_first || pe > ppc_event_last)
223                 return (EINVAL);
224
225         for (i = 0; i < ppc_event_codes_size; i++) {
226                 if (ppc_event_codes[i].pe_event == pe) {
227                         config = ppc_event_codes[i].pe_code;
228                         counter =  ppc_event_codes[i].pe_flags;
229                         break;
230                 }
231         }
232         if (i == ppc_event_codes_size)
233                 return (EINVAL);
234
235         if ((counter & (1 << ri)) == 0)
236                 return (EINVAL);
237
238         if (caps & PMC_CAP_SYSTEM)
239                 config |= POWERPC_PMC_KERNEL_ENABLE;
240         if (caps & PMC_CAP_USER)
241                 config |= POWERPC_PMC_USER_ENABLE;
242         if ((caps & (PMC_CAP_USER | PMC_CAP_SYSTEM)) == 0)
243                 config |= POWERPC_PMC_ENABLE;
244
245         pm->pm_md.pm_powerpc.pm_powerpc_evsel = config;
246
247         PMCDBG3(MDP,ALL,1,"powerpc-allocate cpu=%d ri=%d -> config=0x%x",
248             cpu, ri, config);
249         return (0);
250 }
251
252 int
253 powerpc_release_pmc(int cpu, int ri, struct pmc *pmc)
254 {
255         struct pmc_hw *phw __diagused;
256
257         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
258             ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu));
259         KASSERT(ri >= 0 && ri < ppc_max_pmcs,
260             ("[powerpc,%d] illegal row-index %d", __LINE__, ri));
261
262         phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri];
263         KASSERT(phw->phw_pmc == NULL,
264             ("[powerpc,%d] PHW pmc %p non-NULL", __LINE__, phw->phw_pmc));
265
266         return (0);
267 }
268
269 int
270 powerpc_start_pmc(int cpu, int ri)
271 {
272         struct pmc *pm;
273
274         PMCDBG2(MDP,STA,1,"powerpc-start cpu=%d ri=%d", cpu, ri);
275         pm = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc;
276         powerpc_set_pmc(cpu, ri, pm->pm_md.pm_powerpc.pm_powerpc_evsel);
277
278         return (0);
279 }
280
281 int
282 powerpc_stop_pmc(int cpu, int ri)
283 {
284         PMCDBG2(MDP,STO,1, "powerpc-stop cpu=%d ri=%d", cpu, ri);
285         powerpc_set_pmc(cpu, ri, PMCN_NONE);
286         return (0);
287 }
288
289 int
290 powerpc_config_pmc(int cpu, int ri, struct pmc *pm)
291 {
292         struct pmc_hw *phw;
293
294         PMCDBG3(MDP,CFG,1, "powerpc-config cpu=%d ri=%d pm=%p", cpu, ri, pm);
295
296         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
297             ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu));
298         KASSERT(ri >= 0 && ri < ppc_max_pmcs,
299             ("[powerpc,%d] illegal row-index %d", __LINE__, ri));
300
301         phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri];
302
303         KASSERT(pm == NULL || phw->phw_pmc == NULL,
304             ("[powerpc,%d] pm=%p phw->pm=%p hwpmc not unconfigured",
305             __LINE__, pm, phw->phw_pmc));
306
307         phw->phw_pmc = pm;
308
309         return (0);
310 }
311
312 pmc_value_t
313 powerpc_pmcn_read_default(unsigned int pmc)
314 {
315         pmc_value_t val;
316
317         if (pmc > ppc_max_pmcs)
318                 panic("Invalid PMC number: %d\n", pmc);
319
320         switch (pmc) {
321         case 0:
322                 val = mfspr(SPR_PMC1);
323                 break;
324         case 1:
325                 val = mfspr(SPR_PMC2);
326                 break;
327         case 2:
328                 val = mfspr(SPR_PMC3);
329                 break;
330         case 3:
331                 val = mfspr(SPR_PMC4);
332                 break;
333         case 4:
334                 val = mfspr(SPR_PMC5);
335                 break;
336         case 5:
337                 val = mfspr(SPR_PMC6);
338                 break;
339         case 6:
340                 val = mfspr(SPR_PMC7);
341                 break;
342         case 7:
343                 val = mfspr(SPR_PMC8);
344                 break;
345         }
346
347         return (val);
348 }
349
350 void
351 powerpc_pmcn_write_default(unsigned int pmc, uint32_t val)
352 {
353         if (pmc > ppc_max_pmcs)
354                 panic("Invalid PMC number: %d\n", pmc);
355
356         switch (pmc) {
357         case 0:
358                 mtspr(SPR_PMC1, val);
359                 break;
360         case 1:
361                 mtspr(SPR_PMC2, val);
362                 break;
363         case 2:
364                 mtspr(SPR_PMC3, val);
365                 break;
366         case 3:
367                 mtspr(SPR_PMC4, val);
368                 break;
369         case 4:
370                 mtspr(SPR_PMC5, val);
371                 break;
372         case 5:
373                 mtspr(SPR_PMC6, val);
374                 break;
375         case 6:
376                 mtspr(SPR_PMC7, val);
377                 break;
378         case 7:
379                 mtspr(SPR_PMC8, val);
380                 break;
381         }
382 }
383
384 int
385 powerpc_read_pmc(int cpu, int ri, pmc_value_t *v)
386 {
387         struct pmc *pm;
388         pmc_value_t p, r, tmp;
389
390         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
391             ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu));
392         KASSERT(ri >= 0 && ri < ppc_max_pmcs,
393             ("[powerpc,%d] illegal row index %d", __LINE__, ri));
394
395         pm  = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc;
396         KASSERT(pm,
397             ("[core,%d] cpu %d ri %d pmc not configured", __LINE__, cpu,
398                 ri));
399
400         /*
401          * After an interrupt occurs because of a PMC overflow, the PMC value
402          * is not always MAX_PMC_VALUE + 1, but may be a little above it.
403          * This may mess up calculations and frustrate machine independent
404          * layer expectations, such as that no value read should be greater
405          * than reload count in sampling mode.
406          * To avoid these issues, use MAX_PMC_VALUE as an upper limit.
407          */
408         p = MIN(powerpc_pmcn_read(ri), POWERPC_MAX_PMC_VALUE);
409         r = pm->pm_sc.pm_reloadcount;
410
411         if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) {
412                 /*
413                  * Special case 1: r is too big
414                  * This usually happens when a PMC write fails, the PMC is
415                  * stopped and then it is read.
416                  *
417                  * Special case 2: PMC was reseted or has a value
418                  * that should not be possible with current r.
419                  *
420                  * In the above cases, just return 0 instead of an arbitrary
421                  * value.
422                  */
423                 if (r > POWERPC_MAX_PMC_VALUE || p + r <= POWERPC_MAX_PMC_VALUE)
424                         tmp = 0;
425                 else
426                         tmp = POWERPC_PERFCTR_VALUE_TO_RELOAD_COUNT(p);
427         } else
428                 tmp = p + (POWERPC_MAX_PMC_VALUE + 1) * PPC_OVERFLOWCNT(pm);
429
430         PMCDBG5(MDP,REA,1,"ppc-read cpu=%d ri=%d -> %jx (%jx,%jx)",
431             cpu, ri, (uintmax_t)tmp, (uintmax_t)PPC_OVERFLOWCNT(pm),
432             (uintmax_t)p);
433         *v = tmp;
434         return (0);
435 }
436
437 int
438 powerpc_write_pmc(int cpu, int ri, pmc_value_t v)
439 {
440         struct pmc *pm;
441         pmc_value_t vlo;
442
443         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
444             ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu));
445         KASSERT(ri >= 0 && ri < ppc_max_pmcs,
446             ("[powerpc,%d] illegal row-index %d", __LINE__, ri));
447
448         pm = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc;
449
450         if (PMC_IS_COUNTING_MODE(PMC_TO_MODE(pm))) {
451                 PPC_OVERFLOWCNT(pm) = v / (POWERPC_MAX_PMC_VALUE + 1);
452                 vlo = v % (POWERPC_MAX_PMC_VALUE + 1);
453         } else if (v > POWERPC_MAX_PMC_VALUE) {
454                 PMCDBG3(MDP,WRI,2,
455                     "powerpc-write cpu=%d ri=%d: PMC value is too big: %jx",
456                     cpu, ri, (uintmax_t)v);
457                 return (EINVAL);
458         } else
459                 vlo = POWERPC_RELOAD_COUNT_TO_PERFCTR_VALUE(v);
460
461         PMCDBG5(MDP,WRI,1,"powerpc-write cpu=%d ri=%d -> %jx (%jx,%jx)",
462             cpu, ri, (uintmax_t)v, (uintmax_t)PPC_OVERFLOWCNT(pm),
463             (uintmax_t)vlo);
464
465         powerpc_pmcn_write(ri, vlo);
466         return (0);
467 }
468
469 int
470 powerpc_pmc_intr(struct trapframe *tf)
471 {
472         struct pmc *pm;
473         struct powerpc_cpu *pc;
474         int cpu, error, i, retval;
475
476         cpu = curcpu;
477         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
478             ("[powerpc,%d] out of range CPU %d", __LINE__, cpu));
479
480         PMCDBG3(MDP,INT,1, "cpu=%d tf=%p um=%d", cpu, (void *) tf,
481             TRAPF_USERMODE(tf));
482
483         retval = 0;
484         pc = powerpc_pcpu[cpu];
485
486         /*
487          * Look for a running, sampling PMC which has overflowed
488          * and which has a valid 'struct pmc' association.
489          */
490         for (i = 0; i < ppc_max_pmcs; i++) {
491                 if (!POWERPC_PMC_HAS_OVERFLOWED(i))
492                         continue;
493                 retval = 1;     /* Found an interrupting PMC. */
494
495                 /*
496                  * Always clear the PMC, to make it stop interrupting.
497                  * If pm is available and in sampling mode, use reload
498                  * count, to make PMC read after stop correct.
499                  * Otherwise, just reset the PMC.
500                  */
501                 if ((pm = pc->pc_ppcpmcs[i].phw_pmc) != NULL &&
502                     PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) {
503                         if (pm->pm_state != PMC_STATE_RUNNING) {
504                                 powerpc_write_pmc(cpu, i,
505                                     pm->pm_sc.pm_reloadcount);
506                                 continue;
507                         }
508                 } else {
509                         if (pm != NULL) { /* !PMC_IS_SAMPLING_MODE */
510                                 PPC_OVERFLOWCNT(pm) = (PPC_OVERFLOWCNT(pm) +
511                                     1) % PPC_OVERFLOWCNT_MAX;
512                                 PMCDBG3(MDP,INT,2,
513                                     "cpu=%d ri=%d: overflowcnt=%d",
514                                     cpu, i, PPC_OVERFLOWCNT(pm));
515                         }
516
517                         powerpc_pmcn_write(i, 0);
518                         continue;
519                 }
520
521                 error = pmc_process_interrupt(PMC_HR, pm, tf);
522                 if (error != 0) {
523                         PMCDBG3(MDP,INT,3,
524                             "cpu=%d ri=%d: error %d processing interrupt",
525                             cpu, i, error);
526                         powerpc_stop_pmc(cpu, i);
527                 }
528
529                 /* Reload sampling count */
530                 powerpc_write_pmc(cpu, i, pm->pm_sc.pm_reloadcount);
531         }
532
533         if (retval)
534                 counter_u64_add(pmc_stats.pm_intr_processed, 1);
535         else
536                 counter_u64_add(pmc_stats.pm_intr_ignored, 1);
537
538         /*
539          * Re-enable PERF exceptions if we were able to find the interrupt
540          * source and handle it. Otherwise, it's better to disable PERF
541          * interrupts, to avoid the risk of processing the same interrupt
542          * forever.
543          */
544         powerpc_resume_pmc(retval != 0);
545         if (retval == 0)
546                 log(LOG_WARNING,
547                     "pmc_intr: couldn't find interrupting PMC on cpu %d - "
548                     "disabling PERF interrupts\n", cpu);
549
550         return (retval);
551 }
552
553 struct pmc_mdep *
554 pmc_md_initialize()
555 {
556         struct pmc_mdep *pmc_mdep;
557         int error;
558         uint16_t vers;
559         
560         /*
561          * Allocate space for pointers to PMC HW descriptors and for
562          * the MDEP structure used by MI code.
563          */
564         powerpc_pcpu = malloc(sizeof(struct powerpc_cpu *) * pmc_cpu_max(), M_PMC,
565                            M_WAITOK|M_ZERO);
566
567         /* Just one class */
568         pmc_mdep = pmc_mdep_alloc(1);
569
570         vers = mfpvr() >> 16;
571
572         pmc_mdep->pmd_switch_in  = powerpc_switch_in;
573         pmc_mdep->pmd_switch_out = powerpc_switch_out;
574         
575         switch (vers) {
576         case MPC7447A:
577         case MPC7448:
578         case MPC7450:
579         case MPC7455:
580         case MPC7457:
581                 error = pmc_mpc7xxx_initialize(pmc_mdep);
582                 break;
583         case IBM970:
584         case IBM970FX:
585         case IBM970MP:
586                 error = pmc_ppc970_initialize(pmc_mdep);
587                 break;
588         case IBMPOWER8E:
589         case IBMPOWER8NVL:
590         case IBMPOWER8:
591         case IBMPOWER9:
592                 error = pmc_power8_initialize(pmc_mdep);
593                 break;
594         case FSL_E500v1:
595         case FSL_E500v2:
596         case FSL_E500mc:
597         case FSL_E5500:
598                 error = pmc_e500_initialize(pmc_mdep);
599                 break;
600         default:
601                 error = -1;
602                 break;
603         }
604
605         if (error != 0) {
606                 pmc_mdep_free(pmc_mdep);
607                 pmc_mdep = NULL;
608         }
609
610         /* Set the value for kern.hwpmc.cpuid */
611         snprintf(pmc_cpuid, sizeof(pmc_cpuid), "%08x", mfpvr());
612
613         return (pmc_mdep);
614 }
615
616 void
617 pmc_md_finalize(struct pmc_mdep *md)
618 {
619
620         free(powerpc_pcpu, M_PMC);
621         powerpc_pcpu = NULL;
622 }
623
624 int
625 pmc_save_user_callchain(uintptr_t *cc, int maxsamples,
626     struct trapframe *tf)
627 {
628         uintptr_t *osp, *sp;
629         int frames = 0;
630
631         cc[frames++] = PMC_TRAPFRAME_TO_PC(tf);
632         sp = (uintptr_t *)PMC_TRAPFRAME_TO_FP(tf);
633         osp = NULL;
634
635         for (; frames < maxsamples; frames++) {
636                 if (sp <= osp)
637                         break;
638                 osp = sp;
639 #ifdef __powerpc64__
640                 /* Check if 32-bit mode. */
641                 if (!(tf->srr1 & PSL_SF)) {
642                         cc[frames] = fuword32((uint32_t *)sp + 1);
643                         sp = (uintptr_t *)(uintptr_t)fuword32(sp);
644                 } else {
645                         cc[frames] = fuword(sp + 2);
646                         sp = (uintptr_t *)fuword(sp);
647                 }
648 #else
649                 cc[frames] = fuword32((uint32_t *)sp + 1);
650                 sp = (uintptr_t *)fuword32(sp);
651 #endif
652         }
653
654         return (frames);
655 }