]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/hwpmc/hwpmc_mips.c
Update to version 3.2.0
[FreeBSD/FreeBSD.git] / sys / dev / hwpmc / hwpmc_mips.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2010, George V. Neville-Neil <gnn@freebsd.org>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 #include "opt_hwpmc_hooks.h"
34
35 #include <sys/param.h>
36 #include <sys/pmc.h>
37 #include <sys/pmckern.h>
38 #include <sys/systm.h>
39
40 #include <machine/pmc_mdep.h>
41 #include <machine/md_var.h>
42 #include <machine/mips_opcode.h>
43 #include <machine/vmparam.h>
44
45 int mips_npmcs;
46
47 /*
48  * Per-processor information.
49  */
50 struct mips_cpu {
51         struct pmc_hw   *pc_mipspmcs;
52 };
53
54 static struct mips_cpu **mips_pcpu;
55
56 #if defined(__mips_n64)
57 #       define  MIPS_IS_VALID_KERNELADDR(reg)   ((((reg) & 3) == 0) && \
58                                         ((vm_offset_t)(reg) >= MIPS_XKPHYS_START))
59 #else
60 #       define  MIPS_IS_VALID_KERNELADDR(reg)   ((((reg) & 3) == 0) && \
61                                         ((vm_offset_t)(reg) >= MIPS_KSEG0_START))
62 #endif
63
64 /*
65  * We need some reasonable default to prevent backtrace code
66  * from wandering too far
67  */
68 #define MAX_FUNCTION_SIZE 0x10000
69 #define MAX_PROLOGUE_SIZE 0x100
70
71 static int
72 mips_allocate_pmc(int cpu, int ri, struct pmc *pm,
73   const struct pmc_op_pmcallocate *a)
74 {
75         enum pmc_event pe;
76         uint32_t caps, config, counter;
77         uint32_t event;
78         int i;
79
80         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
81             ("[mips,%d] illegal CPU value %d", __LINE__, cpu));
82         KASSERT(ri >= 0 && ri < mips_npmcs,
83             ("[mips,%d] illegal row index %d", __LINE__, ri));
84
85         caps = a->pm_caps;
86         if (a->pm_class != mips_pmc_spec.ps_cpuclass)
87                 return (EINVAL);
88         pe = a->pm_ev;
89         counter = MIPS_CTR_ALL;
90         event = 0;
91         for (i = 0; i < mips_event_codes_size; i++) {
92                 if (mips_event_codes[i].pe_ev == pe) {
93                         event = mips_event_codes[i].pe_code;
94                         counter =  mips_event_codes[i].pe_counter;
95                         break;
96                 }
97         }
98
99         if (i == mips_event_codes_size)
100                 return (EINVAL);
101
102         if ((counter != MIPS_CTR_ALL) && (counter != ri))
103                 return (EINVAL);
104
105         config = mips_get_perfctl(cpu, ri, event, caps);
106
107         pm->pm_md.pm_mips_evsel = config;
108
109         PMCDBG2(MDP,ALL,2,"mips-allocate ri=%d -> config=0x%x", ri, config);
110
111         return 0;
112 }
113
114
115 static int
116 mips_read_pmc(int cpu, int ri, pmc_value_t *v)
117 {
118         struct pmc *pm;
119         pmc_value_t tmp;
120
121         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
122             ("[mips,%d] illegal CPU value %d", __LINE__, cpu));
123         KASSERT(ri >= 0 && ri < mips_npmcs,
124             ("[mips,%d] illegal row index %d", __LINE__, ri));
125
126         pm  = mips_pcpu[cpu]->pc_mipspmcs[ri].phw_pmc;
127         tmp = mips_pmcn_read(ri);
128         PMCDBG2(MDP,REA,2,"mips-read id=%d -> %jd", ri, tmp);
129
130         if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
131                 *v = tmp - (1UL << (mips_pmc_spec.ps_counter_width - 1));
132         else
133                 *v = tmp;
134
135         return 0;
136 }
137
138 static int
139 mips_write_pmc(int cpu, int ri, pmc_value_t v)
140 {
141         struct pmc *pm;
142
143         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
144             ("[mips,%d] illegal CPU value %d", __LINE__, cpu));
145         KASSERT(ri >= 0 && ri < mips_npmcs,
146             ("[mips,%d] illegal row-index %d", __LINE__, ri));
147
148         pm  = mips_pcpu[cpu]->pc_mipspmcs[ri].phw_pmc;
149
150         if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
151                 v = (1UL << (mips_pmc_spec.ps_counter_width - 1)) - v;
152         
153         PMCDBG3(MDP,WRI,1,"mips-write cpu=%d ri=%d v=%jx", cpu, ri, v);
154
155         mips_pmcn_write(ri, v);
156
157         return 0;
158 }
159
160 static int
161 mips_config_pmc(int cpu, int ri, struct pmc *pm)
162 {
163         struct pmc_hw *phw;
164
165         PMCDBG3(MDP,CFG,1, "cpu=%d ri=%d pm=%p", cpu, ri, pm);
166
167         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
168             ("[mips,%d] illegal CPU value %d", __LINE__, cpu));
169         KASSERT(ri >= 0 && ri < mips_npmcs,
170             ("[mips,%d] illegal row-index %d", __LINE__, ri));
171
172         phw = &mips_pcpu[cpu]->pc_mipspmcs[ri];
173
174         KASSERT(pm == NULL || phw->phw_pmc == NULL,
175             ("[mips,%d] pm=%p phw->pm=%p hwpmc not unconfigured",
176             __LINE__, pm, phw->phw_pmc));
177
178         phw->phw_pmc = pm;
179
180         return 0;
181 }
182
183 static int
184 mips_start_pmc(int cpu, int ri)
185 {
186         uint32_t config;
187         struct pmc *pm;
188         struct pmc_hw *phw;
189
190         phw    = &mips_pcpu[cpu]->pc_mipspmcs[ri];
191         pm     = phw->phw_pmc;
192         config = pm->pm_md.pm_mips_evsel;
193
194         /* Enable the PMC. */
195         switch (ri) {
196         case 0:
197                 mips_wr_perfcnt0(config);
198                 break;
199         case 1:
200                 mips_wr_perfcnt2(config);
201                 break;
202         default:
203                 break;
204         }
205
206         return 0;
207 }
208
209 static int
210 mips_stop_pmc(int cpu, int ri)
211 {
212         struct pmc *pm;
213         struct pmc_hw *phw;
214
215         phw    = &mips_pcpu[cpu]->pc_mipspmcs[ri];
216         pm     = phw->phw_pmc;
217
218         /*
219          * Disable the PMCs.
220          *
221          * Clearing the entire register turns the counter off as well
222          * as removes the previously sampled event.
223          */
224         switch (ri) {
225         case 0:
226                 mips_wr_perfcnt0(0);
227                 break;
228         case 1:
229                 mips_wr_perfcnt2(0);
230                 break;
231         default:
232                 break;
233         }
234         return 0;
235 }
236
237 static int
238 mips_release_pmc(int cpu, int ri, struct pmc *pmc)
239 {
240         struct pmc_hw *phw;
241
242         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
243             ("[mips,%d] illegal CPU value %d", __LINE__, cpu));
244         KASSERT(ri >= 0 && ri < mips_npmcs,
245             ("[mips,%d] illegal row-index %d", __LINE__, ri));
246
247         phw = &mips_pcpu[cpu]->pc_mipspmcs[ri];
248         KASSERT(phw->phw_pmc == NULL,
249             ("[mips,%d] PHW pmc %p non-NULL", __LINE__, phw->phw_pmc));
250
251         return 0;
252 }
253
254 static int
255 mips_pmc_intr(struct trapframe *tf)
256 {
257         int error;
258         int retval, ri, cpu;
259         struct pmc *pm;
260         struct mips_cpu *pc;
261         uint32_t r0, r2;
262         pmc_value_t r;
263
264         cpu = curcpu;
265         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
266             ("[mips,%d] CPU %d out of range", __LINE__, cpu));
267
268         retval = 0;
269         pc = mips_pcpu[cpu];
270
271         /* Stop PMCs without clearing the counter */
272         r0 = mips_rd_perfcnt0();
273         mips_wr_perfcnt0(r0 & ~(0x1f));
274         r2 = mips_rd_perfcnt2();
275         mips_wr_perfcnt2(r2 & ~(0x1f));
276
277         for (ri = 0; ri < mips_npmcs; ri++) {
278                 pm = mips_pcpu[cpu]->pc_mipspmcs[ri].phw_pmc;
279                 if (pm == NULL)
280                         continue;
281                 if (! PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
282                         continue;
283
284                 r = mips_pmcn_read(ri);
285
286                 /* If bit 31 is set, the counter has overflowed */
287                 if ((r & (1UL << (mips_pmc_spec.ps_counter_width - 1))) == 0)
288                         continue;
289
290                 retval = 1;
291                 if (pm->pm_state != PMC_STATE_RUNNING)
292                         continue;
293                 error = pmc_process_interrupt(PMC_HR, pm, tf);
294                 if (error) {
295                         /* Clear/disable the relevant counter */
296                         if (ri == 0)
297                                 r0 = 0;
298                         else if (ri == 1)
299                                 r2 = 0;
300                         mips_stop_pmc(cpu, ri);
301                 }
302
303                 /* Reload sampling count */
304                 mips_write_pmc(cpu, ri, pm->pm_sc.pm_reloadcount);
305         }
306
307         /*
308          * Re-enable the PMC counters where they left off.
309          *
310          * Any counter which overflowed will have its sample count
311          * reloaded in the loop above.
312          */
313         mips_wr_perfcnt0(r0);
314         mips_wr_perfcnt2(r2);
315
316         return retval;
317 }
318
319 static int
320 mips_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc)
321 {
322         int error;
323         struct pmc_hw *phw;
324         char mips_name[PMC_NAME_MAX];
325
326         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
327             ("[mips,%d], illegal CPU %d", __LINE__, cpu));
328         KASSERT(ri >= 0 && ri < mips_npmcs,
329             ("[mips,%d] row-index %d out of range", __LINE__, ri));
330
331         phw = &mips_pcpu[cpu]->pc_mipspmcs[ri];
332         snprintf(mips_name, sizeof(mips_name), "MIPS-%d", ri);
333         if ((error = copystr(mips_name, pi->pm_name, PMC_NAME_MAX,
334             NULL)) != 0)
335                 return error;
336         pi->pm_class = mips_pmc_spec.ps_cpuclass;
337         if (phw->phw_state & PMC_PHW_FLAG_IS_ENABLED) {
338                 pi->pm_enabled = TRUE;
339                 *ppmc          = phw->phw_pmc;
340         } else {
341                 pi->pm_enabled = FALSE;
342                 *ppmc          = NULL;
343         }
344
345         return (0);
346 }
347
348 static int
349 mips_get_config(int cpu, int ri, struct pmc **ppm)
350 {
351         *ppm = mips_pcpu[cpu]->pc_mipspmcs[ri].phw_pmc;
352
353         return 0;
354 }
355
356 /*
357  * XXX don't know what we should do here.
358  */
359 static int
360 mips_pmc_switch_in(struct pmc_cpu *pc, struct pmc_process *pp)
361 {
362         return 0;
363 }
364
365 static int
366 mips_pmc_switch_out(struct pmc_cpu *pc, struct pmc_process *pp)
367 {
368         return 0;
369 }
370
371 static int
372 mips_pcpu_init(struct pmc_mdep *md, int cpu)
373 {
374         int first_ri, i;
375         struct pmc_cpu *pc;
376         struct mips_cpu *pac;
377         struct pmc_hw  *phw;
378
379         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
380             ("[mips,%d] wrong cpu number %d", __LINE__, cpu));
381         PMCDBG1(MDP,INI,1,"mips-init cpu=%d", cpu);
382
383         mips_pcpu[cpu] = pac = malloc(sizeof(struct mips_cpu), M_PMC,
384             M_WAITOK|M_ZERO);
385         pac->pc_mipspmcs = malloc(sizeof(struct pmc_hw) * mips_npmcs,
386             M_PMC, M_WAITOK|M_ZERO);
387         pc = pmc_pcpu[cpu];
388         first_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_MIPS].pcd_ri;
389         KASSERT(pc != NULL, ("[mips,%d] NULL per-cpu pointer", __LINE__));
390
391         for (i = 0, phw = pac->pc_mipspmcs; i < mips_npmcs; i++, phw++) {
392                 phw->phw_state    = PMC_PHW_FLAG_IS_ENABLED |
393                     PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(i);
394                 phw->phw_pmc      = NULL;
395                 pc->pc_hwpmcs[i + first_ri] = phw;
396         }
397
398         /*
399          * Clear the counter control register which has the effect
400          * of disabling counting.
401          */
402         for (i = 0; i < mips_npmcs; i++)
403                 mips_pmcn_write(i, 0);
404
405         return 0;
406 }
407
408 static int
409 mips_pcpu_fini(struct pmc_mdep *md, int cpu)
410 {
411         return 0;
412 }
413
414 struct pmc_mdep *
415 pmc_mips_initialize()
416 {
417         struct pmc_mdep *pmc_mdep;
418         struct pmc_classdep *pcd;
419         
420         /*
421          * TODO: Use More bit of PerfCntlX register to detect actual 
422          * number of counters
423          */
424         mips_npmcs = 2;
425         
426         PMCDBG1(MDP,INI,1,"mips-init npmcs=%d", mips_npmcs);
427
428         /*
429          * Allocate space for pointers to PMC HW descriptors and for
430          * the MDEP structure used by MI code.
431          */
432         mips_pcpu = malloc(sizeof(struct mips_cpu *) * pmc_cpu_max(), M_PMC,
433                            M_WAITOK|M_ZERO);
434
435         /* Just one class */
436         pmc_mdep = pmc_mdep_alloc(1);
437
438         pmc_mdep->pmd_cputype = mips_pmc_spec.ps_cputype;
439
440         pcd = &pmc_mdep->pmd_classdep[PMC_MDEP_CLASS_INDEX_MIPS];
441         pcd->pcd_caps  = mips_pmc_spec.ps_capabilities;
442         pcd->pcd_class = mips_pmc_spec.ps_cpuclass;
443         pcd->pcd_num   = mips_npmcs;
444         pcd->pcd_ri    = pmc_mdep->pmd_npmc;
445         pcd->pcd_width = mips_pmc_spec.ps_counter_width;
446
447         pcd->pcd_allocate_pmc   = mips_allocate_pmc;
448         pcd->pcd_config_pmc     = mips_config_pmc;
449         pcd->pcd_pcpu_fini      = mips_pcpu_fini;
450         pcd->pcd_pcpu_init      = mips_pcpu_init;
451         pcd->pcd_describe       = mips_describe;
452         pcd->pcd_get_config     = mips_get_config;
453         pcd->pcd_read_pmc       = mips_read_pmc;
454         pcd->pcd_release_pmc    = mips_release_pmc;
455         pcd->pcd_start_pmc      = mips_start_pmc;
456         pcd->pcd_stop_pmc       = mips_stop_pmc;
457         pcd->pcd_write_pmc      = mips_write_pmc;
458
459         pmc_mdep->pmd_intr       = mips_pmc_intr;
460         pmc_mdep->pmd_switch_in  = mips_pmc_switch_in;
461         pmc_mdep->pmd_switch_out = mips_pmc_switch_out;
462         
463         pmc_mdep->pmd_npmc   += mips_npmcs;
464
465         return (pmc_mdep);
466 }
467
468 void
469 pmc_mips_finalize(struct pmc_mdep *md)
470 {
471         (void) md;
472 }
473
474 #ifdef  HWPMC_MIPS_BACKTRACE
475
476 static int
477 pmc_next_frame(register_t *pc, register_t *sp)
478 {
479         InstFmt i;
480         uintptr_t va;
481         uint32_t instr, mask;
482         int more, stksize;
483         register_t ra = 0;
484
485         /* Jump here after a nonstandard (interrupt handler) frame */
486         stksize = 0;
487
488         /* check for bad SP: could foul up next frame */
489         if (!MIPS_IS_VALID_KERNELADDR(*sp)) {
490                 goto error;
491         }
492
493         /* check for bad PC */
494         if (!MIPS_IS_VALID_KERNELADDR(*pc)) {
495                 goto error;
496         }
497
498         /*
499          * Find the beginning of the current subroutine by scanning
500          * backwards from the current PC for the end of the previous
501          * subroutine.
502          */
503         va = *pc - sizeof(int);
504         while (1) {
505                 instr = *((uint32_t *)va);
506
507                 /* [d]addiu sp,sp,-X */
508                 if (((instr & 0xffff8000) == 0x27bd8000)
509                     || ((instr & 0xffff8000) == 0x67bd8000))
510                         break;
511
512                 /* jr   ra */
513                 if (instr == 0x03e00008) {
514                         /* skip over branch-delay slot instruction */
515                         va += 2 * sizeof(int);
516                         break;
517                 }
518
519                 va -= sizeof(int);
520         }
521
522         /* skip over nulls which might separate .o files */
523         while ((instr = *((uint32_t *)va)) == 0)
524                 va += sizeof(int);
525
526         /* scan forwards to find stack size and any saved registers */
527         stksize = 0;
528         more = 3;
529         mask = 0;
530         for (; more; va += sizeof(int),
531             more = (more == 3) ? 3 : more - 1) {
532                 /* stop if hit our current position */
533                 if (va >= *pc)
534                         break;
535                 instr = *((uint32_t *)va);
536                 i.word = instr;
537                 switch (i.JType.op) {
538                 case OP_SPECIAL:
539                         switch (i.RType.func) {
540                         case OP_JR:
541                         case OP_JALR:
542                                 more = 2;       /* stop after next instruction */
543                                 break;
544
545                         case OP_SYSCALL:
546                         case OP_BREAK:
547                                 more = 1;       /* stop now */
548                         }
549                         break;
550
551                 case OP_BCOND:
552                 case OP_J:
553                 case OP_JAL:
554                 case OP_BEQ:
555                 case OP_BNE:
556                 case OP_BLEZ:
557                 case OP_BGTZ:
558                         more = 2;       /* stop after next instruction */
559                         break;
560
561                 case OP_COP0:
562                 case OP_COP1:
563                 case OP_COP2:
564                 case OP_COP3:
565                         switch (i.RType.rs) {
566                         case OP_BCx:
567                         case OP_BCy:
568                                 more = 2;       /* stop after next instruction */
569                         }
570                         break;
571
572                 case OP_SW:
573                 case OP_SD:
574                         /* 
575                          * SP is being saved using S8(FP). Most likely it indicates
576                          * that SP is modified in the function and we can't get
577                          * its value safely without emulating code backward
578                          * So just bail out on functions like this
579                          */
580                         if ((i.IType.rs == 30) && (i.IType.rt = 29))
581                                 return (-1);
582
583                         /* look for saved registers on the stack */
584                         if (i.IType.rs != 29)
585                                 break;
586                         /* only restore the first one */
587                         if (mask & (1 << i.IType.rt))
588                                 break;
589                         mask |= (1 << i.IType.rt);
590                         if (i.IType.rt == 31)
591                                 ra = *((register_t *)(*sp + (short)i.IType.imm));
592                         break;
593
594                 case OP_ADDI:
595                 case OP_ADDIU:
596                 case OP_DADDI:
597                 case OP_DADDIU:
598                         /* look for stack pointer adjustment */
599                         if (i.IType.rs != 29 || i.IType.rt != 29)
600                                 break;
601                         stksize = -((short)i.IType.imm);
602                 }
603         }
604
605         if (!MIPS_IS_VALID_KERNELADDR(ra))
606                 return (-1);
607
608         *pc = ra;
609         *sp += stksize;
610
611         return (0);
612
613 error:
614         return (-1);
615 }
616
617 static int
618 pmc_next_uframe(register_t *pc, register_t *sp, register_t *ra)
619 {
620         int offset, registers_on_stack;
621         uint32_t opcode, mask;
622         register_t function_start;
623         int stksize;
624         InstFmt i;
625
626         registers_on_stack = 0;
627         mask = 0;
628         function_start = 0;
629         offset = 0;
630         stksize = 0;
631
632         while (offset < MAX_FUNCTION_SIZE) {
633                 opcode = fuword32((void *)(*pc - offset));
634
635                 /* [d]addiu sp, sp, -X*/
636                 if (((opcode & 0xffff8000) == 0x27bd8000)
637                     || ((opcode & 0xffff8000) == 0x67bd8000)) {
638                         function_start = *pc - offset;
639                         registers_on_stack = 1;
640                         break;
641                 }
642
643                 /* lui gp, X */
644                 if ((opcode & 0xffff8000) == 0x3c1c0000) {
645                         /*
646                          * Function might start with this instruction
647                          * Keep an eye on "jr ra" and sp correction
648                          * with positive value further on
649                          */
650                         function_start = *pc - offset;
651                 }
652
653                 if (function_start) {
654                         /*
655                          * Stop looking further. Possible end of
656                          * function instruction: it means there is no
657                          * stack modifications, sp is unchanged
658                          */
659
660                         /* [d]addiu sp,sp,X */
661                         if (((opcode & 0xffff8000) == 0x27bd0000)
662                             || ((opcode & 0xffff8000) == 0x67bd0000))
663                                 break;
664
665                         if (opcode == 0x03e00008)
666                                 break;
667                 }
668
669                 offset += sizeof(int);
670         }
671
672         if (!function_start)
673                 return (-1);
674
675         if (registers_on_stack) {
676                 offset = 0;
677                 while ((offset < MAX_PROLOGUE_SIZE)
678                     && ((function_start + offset) < *pc)) {
679                         i.word = fuword32((void *)(function_start + offset));
680                         switch (i.JType.op) {
681                         case OP_SW:
682                                 /* look for saved registers on the stack */
683                                 if (i.IType.rs != 29)
684                                         break;
685                                 /* only restore the first one */
686                                 if (mask & (1 << i.IType.rt))
687                                         break;
688                                 mask |= (1 << i.IType.rt);
689                                 if (i.IType.rt == 31)
690                                         *ra = fuword32((void *)(*sp + (short)i.IType.imm));
691                                 break;
692
693 #if defined(__mips_n64)
694                         case OP_SD:
695                                 /* look for saved registers on the stack */
696                                 if (i.IType.rs != 29)
697                                         break;
698                                 /* only restore the first one */
699                                 if (mask & (1 << i.IType.rt))
700                                         break;
701                                 mask |= (1 << i.IType.rt);
702                                 /* ra */
703                                 if (i.IType.rt == 31)
704                                         *ra = fuword64((void *)(*sp + (short)i.IType.imm));
705                         break;
706 #endif
707
708                         case OP_ADDI:
709                         case OP_ADDIU:
710                         case OP_DADDI:
711                         case OP_DADDIU:
712                                 /* look for stack pointer adjustment */
713                                 if (i.IType.rs != 29 || i.IType.rt != 29)
714                                         break;
715                                 stksize = -((short)i.IType.imm);
716                         }
717
718                         offset += sizeof(int);
719                 }
720         }
721
722         /*
723          * We reached the end of backtrace
724          */
725         if (*pc == *ra)
726                 return (-1);
727
728         *pc = *ra;
729         *sp += stksize;
730
731         return (0);
732 }
733
734 #endif /* HWPMC_MIPS_BACKTRACE */
735
736 struct pmc_mdep *
737 pmc_md_initialize()
738 {
739         return pmc_mips_initialize();
740 }
741
742 void
743 pmc_md_finalize(struct pmc_mdep *md)
744 {
745         return pmc_mips_finalize(md);
746 }
747
748 int
749 pmc_save_kernel_callchain(uintptr_t *cc, int nframes,
750     struct trapframe *tf)
751 {
752         register_t pc, ra, sp;
753         int frames = 0;
754
755         pc = tf->pc;
756         sp = tf->sp;
757         ra = tf->ra;
758
759         cc[frames++] = pc;
760
761 #ifdef  HWPMC_MIPS_BACKTRACE
762         /*
763          * Unwind, and unwind, and unwind
764          */
765         while (1) {
766                 if (frames >= nframes)
767                         break;
768
769                 if (pmc_next_frame(&pc, &sp) < 0)
770                         break;
771
772                 cc[frames++] = pc;
773         }
774 #endif
775
776         return (frames);
777 }
778
779 int
780 pmc_save_user_callchain(uintptr_t *cc, int nframes,
781     struct trapframe *tf)
782 {
783         register_t pc, ra, sp;
784         int frames = 0;
785
786         pc = tf->pc;
787         sp = tf->sp;
788         ra = tf->ra;
789
790         cc[frames++] = pc;
791
792 #ifdef  HWPMC_MIPS_BACKTRACE
793
794         /*
795          * Unwind, and unwind, and unwind
796          */
797         while (1) {
798                 if (frames >= nframes)
799                         break;
800
801                 if (pmc_next_uframe(&pc, &sp, &ra) < 0)
802                         break;
803
804                 cc[frames++] = pc;
805         }
806 #endif
807
808         return (frames);
809 }