static void ev4_cpu_setup(void *x) { struct op_register_config *reg = x; wrperfmon(2, reg->mux_select); wrperfmon(3, reg->proc_mode); }
static void ev67_cpu_setup (void *x) { struct op_register_config *reg = x; wrperfmon(2, reg->mux_select); wrperfmon(3, reg->proc_mode); wrperfmon(6, reg->reset_values | 3); }
static void ev5_reset_ctr(struct op_register_config *reg, unsigned long ctr) { unsigned long values, mask, not_pk, reset_values; mask = (ctr == 0 ? 0xfffful << 48 : ctr == 1 ? 0xfffful << 32 : 0x3fff << 16); not_pk = 1 << 9 | 1 << 8; reset_values = reg->reset_values; if ((reg->proc_mode & not_pk) == not_pk) { values = wrperfmon(5, 0); values = (reset_values & mask) | (values & ~mask & -2); wrperfmon(6, values); } else { wrperfmon(0, -1); values = wrperfmon(5, 0); values = (reset_values & mask) | (values & ~mask & -2); wrperfmon(6, values); wrperfmon(1, reg->enable); } }
static void ev67_reset_ctr(struct op_register_config *reg, unsigned long ctr) { wrperfmon(6, reg->reset_values | (1 << ctr)); }
static void ev67_handle_interrupt(unsigned long which, struct pt_regs *regs, struct op_counter_config *ctr) { unsigned long pmpc, pctr_ctl; int kern = !user_mode(regs); int mispredict = 0; union { unsigned long v; struct { unsigned reserved: 30; /* 0-29 */ unsigned overcount: 3; /* 30-32 */ unsigned icache_miss: 1; /* 33 */ unsigned trap_type: 4; /* 34-37 */ unsigned load_store: 1; /* 38 */ unsigned trap: 1; /* 39 */ unsigned mispredict: 1; /* 40 */ } fields; } i_stat; enum trap_types { TRAP_REPLAY, TRAP_INVALID0, TRAP_DTB_DOUBLE_MISS_3, TRAP_DTB_DOUBLE_MISS_4, TRAP_FP_DISABLED, TRAP_UNALIGNED, TRAP_DTB_SINGLE_MISS, TRAP_DSTREAM_FAULT, TRAP_OPCDEC, TRAP_INVALID1, TRAP_MACHINE_CHECK, TRAP_INVALID2, TRAP_ARITHMETIC, TRAP_INVALID3, TRAP_MT_FPCR, TRAP_RESET }; pmpc = wrperfmon(9, 0); /* ??? Don't know how to handle physical-mode PALcode address. */ if (pmpc & 1) return; pmpc &= ~2; /* clear reserved bit */ i_stat.v = wrperfmon(8, 0); if (i_stat.fields.trap) { switch (i_stat.fields.trap_type) { case TRAP_INVALID1: case TRAP_INVALID2: case TRAP_INVALID3: /* Pipeline redirection ocurred. PMPC points to PALcode. Recognize ITB miss by PALcode offset address, and get actual PC from EXC_ADDR. */ oprofile_add_pc(regs->pc, kern, which); if ((pmpc & ((1 << 15) - 1)) == 581) op_add_pm(regs->pc, kern, which, ctr, PM_ITB_MISS); /* Most other bit and counter values will be those for the first instruction in the fault handler, so we're done. */ return; case TRAP_REPLAY: op_add_pm(pmpc, kern, which, ctr, (i_stat.fields.load_store ? PM_LOAD_STORE : PM_REPLAY)); break; case TRAP_DTB_DOUBLE_MISS_3: case TRAP_DTB_DOUBLE_MISS_4: case TRAP_DTB_SINGLE_MISS: op_add_pm(pmpc, kern, which, ctr, PM_DTB_MISS); break; case TRAP_UNALIGNED: op_add_pm(pmpc, kern, which, ctr, PM_UNALIGNED); break; case TRAP_INVALID0: case TRAP_FP_DISABLED: case TRAP_DSTREAM_FAULT: case TRAP_OPCDEC: case TRAP_MACHINE_CHECK: case TRAP_ARITHMETIC: case TRAP_MT_FPCR: case TRAP_RESET: break; } /* ??? JSR/JMP/RET/COR or HW_JSR/HW_JMP/HW_RET/HW_COR mispredicts do not set this bit but can be recognized by the presence of one of these instructions at the PMPC location with bit 39 set. */ if (i_stat.fields.mispredict) { mispredict = 1; op_add_pm(pmpc, kern, which, ctr, PM_MISPREDICT); } } oprofile_add_pc(pmpc, kern, which); pctr_ctl = wrperfmon(5, 0); if (pctr_ctl & (1UL << 27)) op_add_pm(pmpc, kern, which, ctr, PM_STALLED); /* Unfortunately, TAK is undefined on mispredicted branches. ??? It is also undefined for non-cbranch insns, should check that. */ if (!mispredict && pctr_ctl & (1UL << 0)) op_add_pm(pmpc, kern, which, ctr, PM_TAKEN); }
static void ev67_handle_interrupt(unsigned long which, struct pt_regs *regs, struct op_counter_config *ctr) { unsigned long pmpc, pctr_ctl; int kern = !user_mode(regs); int mispredict = 0; union { unsigned long v; struct { unsigned reserved: 30; unsigned overcount: 3; unsigned icache_miss: 1; unsigned trap_type: 4; unsigned load_store: 1; unsigned trap: 1; unsigned mispredict: 1; } fields; } i_stat; enum trap_types { TRAP_REPLAY, TRAP_INVALID0, TRAP_DTB_DOUBLE_MISS_3, TRAP_DTB_DOUBLE_MISS_4, TRAP_FP_DISABLED, TRAP_UNALIGNED, TRAP_DTB_SINGLE_MISS, TRAP_DSTREAM_FAULT, TRAP_OPCDEC, TRAP_INVALID1, TRAP_MACHINE_CHECK, TRAP_INVALID2, TRAP_ARITHMETIC, TRAP_INVALID3, TRAP_MT_FPCR, TRAP_RESET }; pmpc = wrperfmon(9, 0); if (pmpc & 1) return; pmpc &= ~2; i_stat.v = wrperfmon(8, 0); if (i_stat.fields.trap) { switch (i_stat.fields.trap_type) { case TRAP_INVALID1: case TRAP_INVALID2: case TRAP_INVALID3: oprofile_add_pc(regs->pc, kern, which); if ((pmpc & ((1 << 15) - 1)) == 581) op_add_pm(regs->pc, kern, which, ctr, PM_ITB_MISS); return; case TRAP_REPLAY: op_add_pm(pmpc, kern, which, ctr, (i_stat.fields.load_store ? PM_LOAD_STORE : PM_REPLAY)); break; case TRAP_DTB_DOUBLE_MISS_3: case TRAP_DTB_DOUBLE_MISS_4: case TRAP_DTB_SINGLE_MISS: op_add_pm(pmpc, kern, which, ctr, PM_DTB_MISS); break; case TRAP_UNALIGNED: op_add_pm(pmpc, kern, which, ctr, PM_UNALIGNED); break; case TRAP_INVALID0: case TRAP_FP_DISABLED: case TRAP_DSTREAM_FAULT: case TRAP_OPCDEC: case TRAP_MACHINE_CHECK: case TRAP_ARITHMETIC: case TRAP_MT_FPCR: case TRAP_RESET: break; } if (i_stat.fields.mispredict) { mispredict = 1; op_add_pm(pmpc, kern, which, ctr, PM_MISPREDICT); } } oprofile_add_pc(pmpc, kern, which); pctr_ctl = wrperfmon(5, 0); if (pctr_ctl & (1UL << 27)) op_add_pm(pmpc, kern, which, ctr, PM_STALLED); if (!mispredict && pctr_ctl & (1UL << 0)) op_add_pm(pmpc, kern, which, ctr, PM_TAKEN); }