00001
00002
00003 #ifndef perf_cnt_h
00004 #define perf_cnt_h
00005
00006 #include "types.h"
00007
00008 #include "cpu.h"
00009 #include "types.h"
00010
00011
00012
00013
00014
00015
00016 class Perf_cnt_arch;
00017
00018 class Perf_cnt
00019 {
00020 public:
00021 enum {
00022 Max_slot = 2,
00023 Max_pmc = 4,
00024 };
00025
00026 enum Unit_mask_type
00027 { None, Fixed, Exclusive, Bitmask, };
00028
00029 typedef Mword (*Perf_read_fn)();
00030 private:
00031
00032 public:
00033 enum Perf_event_type
00034 { P5, P6, P4, };
00035
00036 static Perf_read_fn read_pmc[Max_slot];
00037
00038 private:
00039 static Perf_read_fn *read_pmc_fns;
00040 static Perf_read_fn read_pmc_fn[Max_slot];
00041 static Perf_cnt_arch *pcnt;
00042 static char const *perf_type_str;
00043 static Perf_event_type perf_event_type;
00044
00045 public:
00046
00047 static FIASCO_INIT void init();
00048
00049 static inline void set_pmc_fn(Mword slot, Mword nr);
00050
00051
00052 static inline int have_watchdog();
00053
00054
00055 static inline void setup_watchdog(Mword timeout);
00056
00057 static inline void setup_loadcnt();
00058
00059 static inline void start_watchdog();
00060
00061 static inline void stop_watchdog();
00062
00063 static inline void touch_watchdog();
00064
00065
00066 static inline char const * perf_type();
00067
00068
00069 static int setup_pmc(Mword slot, Mword event, Mword user, Mword kern, Mword edge);
00070
00071
00072 static int mode(Mword slot, const char **mode, const char **name, Mword *event, Mword *user, Mword *kern, Mword *edge);
00073
00074 static Mword get_max_perf_event();
00075
00076 static void get_perf_event(Mword nr, unsigned *evntsel, const char **name, const char **desc);
00077
00078 static Mword lookup_event(unsigned evntsel);
00079
00080 static void get_unit_mask(Mword nr, Unit_mask_type *type, Mword *default_value, Mword *nvalues);
00081
00082 static void get_unit_mask_entry(Mword nr, Mword idx, Mword *value, const char **desc);
00083
00085 static void split_event(Mword event, unsigned *evntsel, Mword *unit_mask);
00086
00088 static void combine_event(Mword evntsel, Mword unit_mask, Mword *event);
00089 };
00090
00091 class Perf_cnt_arch
00092 {
00093 public:
00094
00095 virtual int init() = 0;
00096
00097
00098 virtual void set_pmc_event(Mword slot) = 0;
00099
00100 inline void touch_watchdog()
00101 { Cpu::wrmsr(hold_watchdog, _ctr_reg0+pmc_watchdog); }
00102
00103 protected:
00104 Mword _nr_regs;
00105 Mword _sel_reg0;
00106 Mword _ctr_reg0;
00107 Mword _watchdog;
00108
00109 typedef struct
00110 {
00111 char user;
00112 char kern;
00113 char edge;
00114 Mword pmc;
00115 Mword bitmask;
00116 Mword evnt;
00117 } Event;
00118
00119 static Mword pmc_watchdog;
00120 static Mword pmc_loadcnt;
00121 static Signed64 hold_watchdog;
00122 static Event pmc_event[Perf_cnt::Max_slot];
00123 static char pmc_alloc[Perf_cnt::Max_pmc];
00124
00125 public:
00126 inline Mword watchdog_allocated();
00127
00128 inline Mword loadcnt_allocated();
00129
00130 virtual void clear_pmc(Mword reg_nr);
00131
00132 void mode(Mword slot, const char **mode, Mword *event, Mword *user, Mword *kern, Mword *edge);
00133
00134 void setup_pmc(Mword slot, Mword bitmask, Mword event, Mword user, Mword kern, Mword edge);
00135
00136 virtual void start_pmc(Mword );
00137
00138
00139 inline int have_watchdog();
00140
00141 void setup_watchdog(Mword timeout);
00142
00143 void setup_loadcnt();
00144
00145 virtual void init_watchdog();
00146
00147 virtual void init_loadcnt();
00148
00149
00150 virtual void start_watchdog();
00151
00152
00153 virtual void stop_watchdog();
00154
00155 protected:
00156
00157 inline Perf_cnt_arch(Mword sel_reg0, Mword ctr_reg0, Mword nr_regs, Mword watchdog);
00158
00159 private:
00160 void alloc_watchdog();
00161
00162 void alloc_loadcnt();
00163
00164
00165
00166 int alloc_pmc(Mword slot, Mword bitmask);
00167 };
00168
00169 class Perf_cnt_p5 : public Perf_cnt_arch {
00170 public:
00171
00172
00173
00174 inline Perf_cnt_p5();
00175
00176 private:
00177 FIASCO_INIT int init();
00178
00179 void set_pmc_event(Mword slot);
00180 };
00181 class Perf_cnt_p6 : public Perf_cnt_arch {
00182 public:
00183
00184
00185
00186 inline Perf_cnt_p6();
00187
00188 protected:
00189 Perf_cnt_p6(Mword sel_reg0, Mword ctr_reg0, Mword nr_regs, Mword watchdog);
00190
00191 private:
00192 FIASCO_INIT int init();
00193
00194 void set_pmc_event(Mword slot);
00195
00196 void start_pmc(Mword );
00197
00198 void init_watchdog();
00199
00200 void init_loadcnt();
00201
00202 void start_watchdog();
00203
00204 void stop_watchdog();
00205 };
00206 class Perf_cnt_k7 : public Perf_cnt_p6 {
00207 public:
00208
00209
00210
00211 inline Perf_cnt_k7();
00212
00213 private:
00214 void start_pmc(Mword reg_nr);
00215
00216 void init_watchdog();
00217
00218 void init_loadcnt();
00219 };
00220 class Perf_cnt_p4 : public Perf_cnt_arch {
00221 public:
00222
00223
00224 inline Perf_cnt_p4();
00225
00226 private:
00227 static inline Mword escr_event_select(Mword n);
00228
00229 static inline Mword escr_event_mask(Mword n);
00230
00231 static inline Mword cccr_threshold(Mword n);
00232
00233 static inline Mword cccr_escr_select(Mword n);
00234
00235 FIASCO_INIT int init();
00236
00237 void set_pmc_event(Mword );
00238
00239 void start_pmc(Mword reg_nr);
00240
00241 void init_watchdog();
00242
00243 void init_loadcnt();
00244
00245 void start_watchdog();
00246
00247 void stop_watchdog();
00248 };
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 inline int
00259 Perf_cnt::have_watchdog()
00260 { return (pcnt && pcnt->have_watchdog()); }
00261
00262
00263
00264
00265 inline void
00266 Perf_cnt::setup_watchdog(Mword timeout)
00267 {
00268 if (pcnt)
00269 pcnt->setup_watchdog(timeout);
00270 }
00271
00272
00273
00274 inline void
00275 Perf_cnt::setup_loadcnt()
00276 {
00277 if (pcnt)
00278 pcnt->setup_loadcnt();
00279 }
00280
00281
00282
00283 inline void
00284 Perf_cnt::start_watchdog()
00285 {
00286 if (pcnt && pcnt->watchdog_allocated())
00287 {
00288 pcnt->touch_watchdog();
00289 pcnt->start_watchdog();
00290 }
00291 }
00292
00293
00294
00295 inline void
00296 Perf_cnt::stop_watchdog()
00297 {
00298 if (pcnt && pcnt->watchdog_allocated())
00299 pcnt->stop_watchdog();
00300 }
00301
00302
00303
00304 inline void
00305 Perf_cnt::touch_watchdog()
00306 {
00307 if (pcnt && pcnt->watchdog_allocated())
00308 pcnt->touch_watchdog();
00309 }
00310
00311
00312
00313
00314 inline char const *
00315 Perf_cnt::perf_type()
00316 { return perf_type_str; }
00317
00318
00319
00320 inline Mword
00321 Perf_cnt_arch::watchdog_allocated()
00322 { return (pmc_watchdog != (Mword)-1); }
00323
00324
00325
00326 inline Mword
00327 Perf_cnt_arch::loadcnt_allocated()
00328 { return (pmc_loadcnt != (Mword)-1); }
00329
00330
00331
00332
00333 inline int
00334 Perf_cnt_arch::have_watchdog()
00335 { return _watchdog; }
00336
00337
00338
00339
00340
00341 inline Perf_cnt_arch::Perf_cnt_arch(Mword sel_reg0, Mword ctr_reg0,
00342 Mword nr_regs, Mword watchdog)
00343 {
00344 _sel_reg0 = sel_reg0;
00345 _ctr_reg0 = ctr_reg0;
00346 _nr_regs = nr_regs;
00347 _watchdog = watchdog;
00348
00349 for (Mword slot=0; slot<Perf_cnt::Max_slot; slot++)
00350 {
00351 pmc_event[slot].pmc = (Mword)-1;
00352 pmc_event[slot].edge = 0;
00353 }
00354 }
00355
00356 #endif // perf_cnt_h