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