33 class Tb_entry_formatter;
35 struct Tb_log_table_entry
39 Tb_entry_formatter *fmt;
42 extern Tb_log_table_entry _log_table[];
43 extern Tb_log_table_entry _log_table_end;
50 Mword _number; ///< event number
51 Address _ip; ///< instruction pointer
52 Context const *_ctx; ///< Context
53 Unsigned64 _tsc; ///< time stamp counter
54 Unsigned32 _pmc1; ///< performance counter value 1
55 Unsigned32 _pmc2; ///< performance counter value 2
56 Unsigned32 _kclock; ///< lower 32 bits of kernel clock
57 Unsigned8 _type; ///< type of entry
58 Unsigned8 _cpu; ///< CPU
60 static Mword (*rdcnt1)();
61 static Mword (*rdcnt2)();
67 Group_order() : _o(0) {} // not grouped
68 Group_order(unsigned v) : _o(2 + v) {}
69 static Group_order none() { return Group_order(); }
70 static Group_order last() { return Group_order(255, true); }
71 static Group_order first() { return Group_order(0); }
72 static Group_order direct() { return Group_order(1, true); }
74 bool not_grouped() const { return _o == 0; }
75 bool is_direct() const { return _o == 1; }
76 bool is_first() const { return _o == 2; }
77 bool is_last() const { return _o == 255; }
78 bool grouped() const { return _o >= 2; }
79 unsigned char depth() const { return _o - 2; }
82 Group_order(unsigned char v, bool) : _o(v) {}
86 Group_order has_partner() const { return Group_order::none(); }
87 Group_order is_partner(Tb_entry const *) const { return Group_order::none(); }
88 Mword partner() const { return 0; }
90 } __attribute__((__packed__, __aligned__(8)));
93 class Tb_entry_union : public Tb_entry
96 char _padding[Tb_entry_size - sizeof(Tb_entry)];
99 static_assert(sizeof(Tb_entry_union) == Tb_entry::Tb_entry_size,
100 "Tb_entry_union has the wrong size");
102 struct Tb_entry_empty : public Tb_entry
104 unsigned print(int, char *) const { return 0; }
107 class Tb_entry_formatter
110 typedef Tb_entry::Group_order Group_order;
112 virtual unsigned print(Tb_entry const *e, int max, char *buf) const = 0;
113 virtual Group_order has_partner(Tb_entry const *e) const = 0;
114 virtual Group_order is_pair(Tb_entry const *e, Tb_entry const *n) const = 0;
115 virtual Mword partner(Tb_entry const *e) const = 0;
117 static Tb_entry_formatter const *get_fmt(Tb_entry const *e)
119 if (e->type() >= Tbuf_dynentries)
120 return _log_table[e->type() - Tbuf_dynentries].fmt;
122 return _fixed[e->type()];
126 static Tb_entry_formatter const *_fixed[];
130 template< typename T >
131 class Tb_entry_formatter_t : public Tb_entry_formatter
134 typedef T const *Const_ptr;
137 unsigned print(Tb_entry const *e, int max, char *buf) const
138 { return static_cast<Const_ptr>(e)->print(max, buf); }
140 Group_order has_partner(Tb_entry const *e) const
141 { return static_cast<Const_ptr>(e)->has_partner(); }
143 Group_order is_pair(Tb_entry const *e, Tb_entry const *n) const
145 //assert (get_fmt(e) == &singleton);
147 if (&singleton == get_fmt(n))
148 return static_cast<Const_ptr>(e)->is_partner(static_cast<Const_ptr>(n));
149 return Tb_entry::Group_order::none();
152 Mword partner(Tb_entry const *e) const
153 { return static_cast<Const_ptr>(e)->partner(); }
155 static Tb_entry_formatter_t const singleton;
159 Tb_entry_formatter_t<T> const Tb_entry_formatter_t<T>::singleton;
163 class Tb_entry_ipc : public Tb_entry
166 L4_msg_tag _tag; ///< message tag
167 Mword _dword[2]; ///< first two message words
168 L4_obj_ref _dst; ///< destination id
171 L4_timeout_pair _timeout; ///< timeout
173 Tb_entry_ipc() : _timeout(0) {}
174 unsigned print(int max, char *buf) const;
177 /** logged ipc result. */
178 class Tb_entry_ipc_res : public Tb_entry
181 L4_msg_tag _tag; ///< message tag
182 Mword _dword[2]; ///< first two dwords
183 L4_error _result; ///< result
184 Mword _from; ///< receive descriptor
185 Mword _pair_event; ///< referred event
186 Unsigned8 _have_snd; ///< ipc had send part
187 Unsigned8 _is_np; ///< next period bit set
189 unsigned print(int max, char *buf) const;
192 /** logged ipc for user level tracing with Vampir. */
193 class Tb_entry_ipc_trace : public Tb_entry
196 Unsigned64 _snd_tsc; ///< entry tsc
197 L4_msg_tag _result; ///< result
198 L4_obj_ref _snd_dst; ///< send destination
199 Mword _rcv_dst; ///< rcv partner
203 unsigned print(int max, char *buf) const;
207 /** logged short-cut ipc failed. */
208 class Tb_entry_ipc_sfl : public Tb_entry_base
211 Global_id _from; ///< short ipc rcv descriptor
212 L4_timeout_pair _timeout; ///< ipc timeout
213 Global_id _dst; ///< partner
214 Unsigned8 _is_irq, _snd_lst, _dst_ok, _dst_lck, _preempt;
218 /** logged pagefault. */
219 class Tb_entry_pf : public Tb_entry
222 Address _pfa; ///< pagefault address
223 Mword _error; ///< pagefault error code
226 unsigned print(int max, char *buf) const;
229 /** pagefault result. */
230 class Tb_entry_pf_res : public Tb_entry
237 unsigned print(int max, char *buf) const;
241 /** logged kernel event. */
242 template<typename BASE, unsigned TAG>
243 class Tb_entry_ke_t : public BASE
248 char msg[BASE::Tb_entry_size - sizeof(BASE)];
255 } __attribute__((__packed__));
257 typedef Tb_entry_ke_t<Tb_entry, Tbuf_ke> Tb_entry_ke;
259 class Tb_entry_ke_reg_b : public Tb_entry
263 } __attribute__((__packed__));
265 class Tb_entry_ke_reg : public Tb_entry_ke_t<Tb_entry_ke_reg_b, Tbuf_ke_reg>
269 /** logged breakpoint. */
270 class Tb_entry_bp : public Tb_entry
273 Address _address; ///< breakpoint address
274 int _len; ///< breakpoint length
275 Mword _value; ///< value at address
276 int _mode; ///< breakpoint mode
278 unsigned print(int max, char *buf) const;
281 /** logged context switch. */
282 class Tb_entry_ctx_sw : public Tb_entry
287 Context const *dst; ///< switcher target
288 Context const *dst_orig;
291 Space const *from_space;
292 Sched_context const *from_sched;
294 unsigned print(int max, char *buf) const;
295 } __attribute__((packed));
297 /** logged scheduling event. */
298 class Tb_entry_sched : public Tb_entry
302 Context const *owner;
306 unsigned long quantum;
308 unsigned print(int max, char *buf) const;
309 } __attribute__((packed));
311 /** logged binary kernel event. */
312 class Tb_entry_ke_bin : public Tb_entry
315 char _msg[Tb_entry_size - sizeof(Tb_entry)];
326 #include "entry_frame.h"
329 #include "static_init.h"
330 #include "trap_state.h"
333 PROTECTED static Mword Tb_entry::dummy_read_pmc() { return 0; }
335 Mword (*Tb_entry::rdcnt1)() = dummy_read_pmc;
336 Mword (*Tb_entry::rdcnt2)() = dummy_read_pmc;
337 Tb_entry_formatter const *Tb_entry_formatter::_fixed[Tbuf_dynentries];
342 Tb_entry_formatter::set_fixed(unsigned type, Tb_entry_formatter const *f)
344 if (type >= Tbuf_dynentries)
353 Tb_entry::set_rdcnt(int num, Mword (*f)())
360 case 0: rdcnt1 = f; break;
361 case 1: rdcnt2 = f; break;
368 { _type = Tbuf_unused; }
370 PUBLIC inline NEEDS["kip.h", "globals.h"]
372 Tb_entry::set_global(char type, Context const *ctx, Address ip)
377 _kclock = (Unsigned32)Kip::k()->clock;
378 _cpu = current_cpu();
384 { _type |= Tbuf_hidden; }
389 { _type &= ~Tbuf_hidden; }
398 Tb_entry::ctx() const
403 Tb_entry::type() const
404 { return _type & (Tbuf_max-1); }
408 Tb_entry::hidden() const
409 { return _type & Tbuf_hidden; }
413 Tb_entry::number() const
418 Tb_entry::number(Mword number)
419 { _number = number; }
424 { _pmc1 = rdcnt1(); }
429 { _pmc2 = rdcnt2(); }
433 Tb_entry::kclock() const
438 Tb_entry::cpu() const
443 Tb_entry::tsc() const
448 Tb_entry::pmc1() const
453 Tb_entry::pmc2() const
457 PUBLIC inline NEEDS ["entry_frame.h"]
459 Tb_entry_ipc::set(Context const *ctx, Mword ip, Syscall_frame *ipc_regs, Utcb *utcb,
460 Mword dbg_id, Unsigned64 left)
462 set_global(Tbuf_ipc, ctx, ip);
463 _dst = ipc_regs->ref();
464 _label = ipc_regs->from_spec();
469 _timeout = ipc_regs->timeout();
470 _tag = ipc_regs->tag();
471 if (ipc_regs->next_period())
473 _dword[0] = (Unsigned32)(left & 0xffffffff);
474 _dword[1] = (Unsigned32)(left >> 32);
479 register Mword tmp0 = utcb->values[0];
480 register Mword tmp1 = utcb->values[1];
488 Tb_entry_ipc::ipc_type() const
489 { return _dst.op(); }
493 Tb_entry_ipc::dbg_id() const
498 Tb_entry_ipc::dst() const
503 Tb_entry_ipc::timeout() const
508 Tb_entry_ipc::tag() const
513 Tb_entry_ipc::label() const
518 Tb_entry_ipc::dword(unsigned index) const
519 { return _dword[index]; }
522 PUBLIC inline NEEDS ["entry_frame.h"]
524 Tb_entry_ipc_res::set(Context const *ctx, Mword ip, Syscall_frame *ipc_regs,
526 Mword result, Mword pair_event, Unsigned8 have_snd,
529 set_global(Tbuf_ipc_res, ctx, ip);
531 register Mword tmp0 = utcb->values[0];
532 register Mword tmp1 = utcb->values[1];
535 _tag = ipc_regs->tag();
536 _pair_event = pair_event;
537 _result = L4_error::from_raw(result);
538 _from = ipc_regs->from_spec();
539 _have_snd = have_snd;
545 Tb_entry_ipc_res::have_snd() const
546 { return _have_snd; }
550 Tb_entry_ipc_res::is_np() const
555 Tb_entry_ipc_res::from() const
560 Tb_entry_ipc_res::result() const
565 Tb_entry_ipc_res::tag() const
570 Tb_entry_ipc_res::dword(unsigned index) const
571 { return _dword[index]; }
575 Tb_entry_ipc_res::pair_event() const
576 { return _pair_event; }
581 Tb_entry_ipc_trace::set(Context const *ctx, Mword ip, Unsigned64 snd_tsc,
582 L4_obj_ref const &snd_dst, Mword rcv_dst,
583 L4_msg_tag result, Unsigned8 snd_desc,
586 set_global(Tbuf_ipc_trace, ctx, ip);
591 _snd_desc = snd_desc;
592 _rcv_desc = rcv_desc;
597 Tb_entry_pf::set(Context const *ctx, Address ip, Address pfa,
598 Mword error, Space *spc)
600 set_global(Tbuf_pf, ctx, ip);
608 Tb_entry_pf::error() const
613 Tb_entry_pf::pfa() const
618 Tb_entry_pf::space() const
624 Tb_entry_pf_res::set(Context const *ctx, Address ip, Address pfa,
625 L4_error err, L4_error ret)
627 set_global(Tbuf_pf_res, ctx, ip);
635 Tb_entry_pf_res::pfa() const
640 Tb_entry_pf_res::err() const
645 Tb_entry_pf_res::ret() const
651 Tb_entry_bp::set(Context const *ctx, Address ip,
652 int mode, int len, Mword value, Address address)
654 set_global(Tbuf_breakpoint, ctx, ip);
665 Tb_entry_bp::mode() const
670 Tb_entry_bp::len() const
675 Tb_entry_bp::value() const
680 Tb_entry_bp::addr() const
685 PUBLIC template<typename BASE, unsigned TAG> inline
687 Tb_entry_ke_t<BASE, TAG>::set(Context const *ctx, Address ip)
688 { this->set_global(TAG, ctx, ip); }
690 PUBLIC template<typename BASE, unsigned TAG> inline
692 Tb_entry_ke_t<BASE, TAG>::set_const(Context const *ctx, Address ip, char const *msg)
694 this->set_global(TAG, ctx, ip);
695 _msg.mptr.tag[0] = 0;
696 _msg.mptr.tag[1] = 1;
700 PUBLIC template<typename BASE, unsigned TAG> inline
702 Tb_entry_ke_t<BASE, TAG>::set_buf(unsigned i, char c)
704 if (i < sizeof(_msg.msg)-1)
705 _msg.msg[i] = c >= ' ' ? c : '.';
708 PUBLIC template<typename BASE, unsigned TAG> inline
710 Tb_entry_ke_t<BASE, TAG>::term_buf(unsigned i)
712 _msg.msg[i < sizeof(_msg.msg)-1 ? i : sizeof(_msg.msg)-1] = '\0';
715 PUBLIC template<typename BASE, unsigned TAG> inline
717 Tb_entry_ke_t<BASE, TAG>::msg() const
719 return _msg.mptr.tag[0] == 0 && _msg.mptr.tag[1] == 1 ? _msg.mptr.ptr : _msg.msg;
724 Tb_entry_ke_bin::set(Context const *ctx, Address ip)
725 { set_global(Tbuf_ke_bin, ctx, ip); }
729 Tb_entry_ke_bin::set_buf(unsigned i, char c)
731 if (i < sizeof(_msg)-1)
737 Tb_entry_ke_reg::set_const(Context const *ctx, Mword eip,
739 Mword v1, Mword v2, Mword v3)
741 Tb_entry_ke_t<Tb_entry_ke_reg_b, Tbuf_ke_reg>::set_const(ctx, eip, msg);