]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/tb_entry.cpp
Some minor fixes.
[l4.git] / kernel / fiasco / src / kern / tb_entry.cpp
1 INTERFACE:
2
3 #include "l4_error.h"
4
5 enum Tbuf_entry_fixed
6 {
7   Tbuf_unused             = 0,
8   Tbuf_pf,
9   Tbuf_ipc,
10   Tbuf_ipc_res,
11   Tbuf_ipc_trace,
12   Tbuf_ke,
13   Tbuf_ke_reg,
14   Tbuf_breakpoint,
15   Tbuf_ke_bin,
16   Tbuf_dynentries,
17
18   Tbuf_max                = 0x80,
19   Tbuf_hidden             = 0x80,
20 };
21
22 #include "l4_types.h"
23
24 class Tb_entry;
25 class Context;
26 class Space;
27 class Sched_context;
28 class Syscall_frame;
29 class Trap_state;
30 class Tb_entry_formatter;
31 class String_buffer;
32
33 struct Tb_log_table_entry
34 {
35   char const *name;
36   unsigned char *patch;
37   Tb_entry_formatter *fmt;
38 };
39
40 extern Tb_log_table_entry _log_table[];
41 extern Tb_log_table_entry _log_table_end;
42
43
44
45 class Tb_entry
46 {
47 protected:
48   Mword         _number;        ///< event number
49   Address       _ip;            ///< instruction pointer
50   Unsigned64    _tsc;           ///< time stamp counter
51   Context const *_ctx;          ///< Context
52   Unsigned32    _pmc1;          ///< performance counter value 1
53   Unsigned32    _pmc2;          ///< performance counter value 2
54   Unsigned32    _kclock;        ///< lower 32 bits of kernel clock
55   Unsigned8     _type;          ///< type of entry
56   Unsigned8     _cpu;           ///< CPU
57
58   static Mword (*rdcnt1)();
59   static Mword (*rdcnt2)();
60
61 public:
62   class Group_order
63   {
64   public:
65     Group_order() : _o(0) {} // not grouped
66     Group_order(unsigned v) : _o(2 + v) {}
67     static Group_order none() { return Group_order(); }
68     static Group_order last() { return Group_order(255, true); }
69     static Group_order first() { return Group_order(0); }
70     static Group_order direct() { return Group_order(1, true); }
71
72     bool not_grouped() const { return _o == 0; }
73     bool is_direct() const { return _o == 1; }
74     bool is_first() const { return _o == 2; }
75     bool is_last() const { return _o == 255; }
76     bool grouped() const { return _o >= 2; }
77     unsigned char depth() const { return _o - 2; }
78
79   private:
80     Group_order(unsigned char v, bool) : _o(v) {}
81     unsigned char _o;
82   };
83
84   Group_order has_partner() const { return Group_order::none(); }
85   Group_order is_partner(Tb_entry const *) const { return Group_order::none(); }
86   Mword partner() const { return 0; }
87
88 } __attribute__((__packed__, __aligned__(8)));
89
90
91 class Tb_entry_union : public Tb_entry
92 {
93 private:
94   char _padding[Tb_entry_size - sizeof(Tb_entry)];
95 };
96
97 static_assert(sizeof(Tb_entry_union) == Tb_entry::Tb_entry_size,
98               "Tb_entry_union has the wrong size");
99
100 struct Tb_entry_empty : public Tb_entry
101 {
102   void print(String_buffer *) const {}
103 };
104
105 class Tb_entry_formatter
106 {
107 public:
108   typedef Tb_entry::Group_order Group_order;
109
110   virtual void print(String_buffer *, Tb_entry const *e) const = 0;
111   virtual Group_order has_partner(Tb_entry const *e) const = 0;
112   virtual Group_order is_pair(Tb_entry const *e, Tb_entry const *n) const = 0;
113   virtual Mword partner(Tb_entry const *e) const = 0;
114
115   static Tb_entry_formatter const *get_fmt(Tb_entry const *e)
116   {
117     if (e->type() >= Tbuf_dynentries)
118       return _log_table[e->type() - Tbuf_dynentries].fmt;
119
120     return _fixed[e->type()];
121   }
122
123 private:
124   static Tb_entry_formatter const *_fixed[];
125 };
126
127
128 template< typename T >
129 class Tb_entry_formatter_t : public Tb_entry_formatter
130 {
131 public:
132   Tb_entry_formatter_t() {}
133
134   typedef T const *Const_ptr;
135   typedef T *Ptr;
136
137   void print(String_buffer *buf, Tb_entry const *e) const
138   { static_cast<Const_ptr>(e)->print(buf); }
139
140   Group_order has_partner(Tb_entry const *e) const
141   { return static_cast<Const_ptr>(e)->has_partner(); }
142
143   Group_order is_pair(Tb_entry const *e, Tb_entry const *n) const
144   {
145     //assert (get_fmt(e) == &singleton);
146
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();
150   }
151
152   Mword partner(Tb_entry const *e) const
153   { return static_cast<Const_ptr>(e)->partner(); }
154
155   static Tb_entry_formatter_t const singleton;
156 };
157
158 template<typename T>
159 Tb_entry_formatter_t<T> const Tb_entry_formatter_t<T>::singleton;
160
161
162 /** logged ipc. */
163 class Tb_entry_ipc : public Tb_entry
164 {
165 private:
166   L4_msg_tag    _tag;           ///< message tag
167   Mword _dword[2];      ///< first two message words
168   L4_obj_ref    _dst;           ///< destination id
169   Mword       _dbg_id;
170   Mword       _label;
171   L4_timeout_pair _timeout;     ///< timeout
172 public:
173   Tb_entry_ipc() : _timeout(0) {}
174   void print(String_buffer *buf) const;
175 };
176
177 /** logged ipc result. */
178 class Tb_entry_ipc_res : public Tb_entry
179 {
180 private:
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
188 public:
189   void print(String_buffer *buf) const;
190 };
191
192 /** logged ipc for user level tracing with Vampir. */
193 class Tb_entry_ipc_trace : public Tb_entry
194 {
195 private:
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
200   Unsigned8     _snd_desc;
201   Unsigned8     _rcv_desc;
202 public:
203   void print(String_buffer *buf) const;
204 };
205
206
207 /** logged pagefault. */
208 class Tb_entry_pf : public Tb_entry
209 {
210 private:
211   Address       _pfa;           ///< pagefault address
212   Mword _error;         ///< pagefault error code
213   Space *_space;
214 public:
215   void print(String_buffer *buf) const;
216 };
217
218 /** logged kernel event. */
219 template<unsigned BASE_SIZE>
220 union Tb_entry_msg
221 {
222   char msg[Tb_entry::Tb_entry_size - BASE_SIZE];
223   struct Ptr
224   {
225     char tag[2];
226     char const *ptr;
227   } mptr;
228
229   void set_const(char const *msg)
230   {
231     mptr.tag[0] = 0;
232     mptr.tag[1] = 1;
233     mptr.ptr = msg;
234   }
235
236   void set_buf(unsigned i, char c)
237   {
238     if (i < sizeof(msg) - 1)
239       msg[i] = c >= ' ' ? c : '.';
240   }
241
242   void term_buf(unsigned i)
243   {
244     msg[i < sizeof(msg) - 1 ? i : sizeof(msg) - 1] = '\0';
245   }
246
247   char const *str() const
248   {
249     return mptr.tag[0] == 0 && mptr.tag[1] == 1 ? mptr.ptr : msg;
250   }
251 };
252
253 class Tb_entry_ke : public Tb_entry
254 {
255 public:
256   Tb_entry_msg<sizeof(Tb_entry)> msg;
257   void set(Context const *ctx, Address ip)
258   { set_global(Tbuf_ke, ctx, ip); }
259 };
260
261 class Tb_entry_ke_reg : public Tb_entry
262 {
263 public:
264   Mword v[3];
265   Tb_entry_msg<sizeof(Tb_entry) + sizeof(v)> msg;
266   void set(Context const *ctx, Address ip)
267   { set_global(Tbuf_ke_reg, ctx, ip); }
268 };
269
270 /** logged breakpoint. */
271 class Tb_entry_bp : public Tb_entry
272 {
273 private:
274   Address       _address;       ///< breakpoint address
275   int           _len;           ///< breakpoint length
276   Mword _value;         ///< value at address
277   int           _mode;          ///< breakpoint mode
278 public:
279   void print(String_buffer *buf) const;
280 };
281
282 /** logged binary kernel event. */
283 class Tb_entry_ke_bin : public Tb_entry
284 {
285 public:
286   char _msg[Tb_entry_size - sizeof(Tb_entry)];
287   enum { SIZE = 30 };
288 };
289
290
291
292 IMPLEMENTATION:
293
294 #include <cstring>
295 #include <cstdarg>
296
297 #include "entry_frame.h"
298 #include "globals.h"
299 #include "kip.h"
300 #include "trap_state.h"
301
302
303 PROTECTED static Mword Tb_entry::dummy_read_pmc() { return 0; }
304
305 Mword (*Tb_entry::rdcnt1)() = dummy_read_pmc;
306 Mword (*Tb_entry::rdcnt2)() = dummy_read_pmc;
307 Tb_entry_formatter const *Tb_entry_formatter::_fixed[Tbuf_dynentries];
308
309
310 PUBLIC static
311 void
312 Tb_entry_formatter::set_fixed(unsigned type, Tb_entry_formatter const *f)
313 {
314   if (type >= Tbuf_dynentries)
315     return;
316
317   _fixed[type] = f;
318 }
319
320
321 PUBLIC static
322 void
323 Tb_entry::set_rdcnt(int num, Mword (*f)())
324 {
325   if (!f)
326     f = dummy_read_pmc;
327
328   switch (num)
329     {
330     case 0: rdcnt1 = f; break;
331     case 1: rdcnt2 = f; break;
332     }
333 }
334
335 PUBLIC inline
336 void
337 Tb_entry::clear()
338 { _type = Tbuf_unused; }
339
340 PUBLIC inline NEEDS["kip.h", "globals.h"]
341 void
342 Tb_entry::set_global(char type, Context const *ctx, Address ip)
343 {
344   _type   = type;
345   _ctx    = ctx;
346   _ip     = ip;
347   _kclock = (Unsigned32)Kip::k()->clock;
348   _cpu    = cxx::int_value<Cpu_number>(current_cpu());
349 }
350
351 PUBLIC inline
352 void
353 Tb_entry::hide()
354 { _type |= Tbuf_hidden; }
355
356 PUBLIC inline
357 void
358 Tb_entry::unhide()
359 { _type &= ~Tbuf_hidden; }
360
361 PUBLIC inline
362 Address
363 Tb_entry::ip() const
364 { return _ip; }
365
366 PUBLIC inline
367 Context const *
368 Tb_entry::ctx() const
369 { return _ctx; }
370
371 PUBLIC inline
372 Unsigned8
373 Tb_entry::type() const
374 { return _type & (Tbuf_max-1); }
375
376 PUBLIC inline
377 int
378 Tb_entry::hidden() const
379 { return _type & Tbuf_hidden; }
380
381 PUBLIC inline
382 Mword
383 Tb_entry::number() const
384 { return _number; }
385
386 PUBLIC inline
387 void
388 Tb_entry::number(Mword number)
389 { _number = number; }
390
391 PUBLIC inline
392 void
393 Tb_entry::rdpmc1()
394 { _pmc1 = rdcnt1(); }
395
396 PUBLIC inline
397 void
398 Tb_entry::rdpmc2()
399 { _pmc2 = rdcnt2(); }
400
401 PUBLIC inline
402 Unsigned32
403 Tb_entry::kclock() const
404 { return _kclock; }
405
406 PUBLIC inline
407 Unsigned8
408 Tb_entry::cpu() const
409 { return _cpu; }
410
411 PUBLIC inline
412 Unsigned64
413 Tb_entry::tsc() const
414 { return _tsc; }
415
416 PUBLIC inline
417 Unsigned32
418 Tb_entry::pmc1() const
419 { return _pmc1; }
420
421 PUBLIC inline
422 Unsigned32
423 Tb_entry::pmc2() const
424 { return _pmc2; }
425
426
427 PUBLIC inline NEEDS ["entry_frame.h"]
428 void
429 Tb_entry_ipc::set(Context const *ctx, Mword ip, Syscall_frame *ipc_regs, Utcb *utcb,
430                   Mword dbg_id, Unsigned64 left)
431 {
432   (void)left;
433   set_global(Tbuf_ipc, ctx, ip);
434   _dst       = ipc_regs->ref();
435   _label     = ipc_regs->from_spec();
436
437
438   _dbg_id = dbg_id;
439
440   _timeout   = ipc_regs->timeout();
441   _tag       = ipc_regs->tag();
442   // hint for gcc
443   Mword tmp0 = utcb->values[0];
444   Mword tmp1 = utcb->values[1];
445   _dword[0]  = tmp0;
446   _dword[1]  = tmp1;
447 }
448
449 PUBLIC inline
450 Mword
451 Tb_entry_ipc::ipc_type() const
452 { return _dst.op(); }
453
454 PUBLIC inline
455 Mword
456 Tb_entry_ipc::dbg_id() const
457 { return _dbg_id; }
458
459 PUBLIC inline
460 L4_obj_ref
461 Tb_entry_ipc::dst() const
462 { return _dst; }
463
464 PUBLIC inline
465 L4_timeout_pair
466 Tb_entry_ipc::timeout() const
467 { return _timeout; }
468
469 PUBLIC inline
470 L4_msg_tag
471 Tb_entry_ipc::tag() const
472 { return _tag; }
473
474 PUBLIC inline
475 Mword
476 Tb_entry_ipc::label() const
477 { return _label; }
478
479 PUBLIC inline
480 Mword
481 Tb_entry_ipc::dword(unsigned index) const
482 { return _dword[index]; }
483
484
485 PUBLIC inline NEEDS ["entry_frame.h"]
486 void
487 Tb_entry_ipc_res::set(Context const *ctx, Mword ip, Syscall_frame *ipc_regs,
488                       Utcb *utcb,
489                       Mword result, Mword pair_event, Unsigned8 have_snd,
490                       Unsigned8 is_np)
491 {
492   set_global(Tbuf_ipc_res, ctx, ip);
493   // hint for gcc
494   Mword tmp0 = utcb->values[0];
495   Mword tmp1 = utcb->values[1];
496   _dword[0]   = tmp0;
497   _dword[1]   = tmp1;
498   _tag        = ipc_regs->tag();
499   _pair_event = pair_event;
500   _result     = L4_error::from_raw(result);
501   _from       = ipc_regs->from_spec();
502   _have_snd   = have_snd;
503   _is_np      = is_np;
504 }
505
506 PUBLIC inline
507 int
508 Tb_entry_ipc_res::have_snd() const
509 { return _have_snd; }
510
511 PUBLIC inline
512 int
513 Tb_entry_ipc_res::is_np() const
514 { return _is_np; }
515
516 PUBLIC inline
517 Mword
518 Tb_entry_ipc_res::from() const
519 { return _from; }
520
521 PUBLIC inline
522 L4_error
523 Tb_entry_ipc_res::result() const
524 { return _result; }
525
526 PUBLIC inline
527 L4_msg_tag
528 Tb_entry_ipc_res::tag() const
529 { return _tag; }
530
531 PUBLIC inline
532 Mword
533 Tb_entry_ipc_res::dword(unsigned index) const
534 { return _dword[index]; }
535
536 PUBLIC inline
537 Mword
538 Tb_entry_ipc_res::pair_event() const
539 { return _pair_event; }
540
541
542 PUBLIC inline
543 void
544 Tb_entry_ipc_trace::set(Context const *ctx, Mword ip, Unsigned64 snd_tsc,
545                         L4_obj_ref const &snd_dst, Mword rcv_dst,
546                         L4_msg_tag result, Unsigned8 snd_desc,
547                         Unsigned8 rcv_desc)
548 {
549   set_global(Tbuf_ipc_trace, ctx, ip);
550   _snd_tsc  = snd_tsc;
551   _snd_dst  = snd_dst;
552   _rcv_dst  = rcv_dst;
553   _result   = result;
554   _snd_desc = snd_desc;
555   _rcv_desc = rcv_desc;
556 }
557
558 PUBLIC inline
559 void
560 Tb_entry_pf::set(Context const *ctx, Address ip, Address pfa,
561                  Mword error, Space *spc)
562 {
563   set_global(Tbuf_pf, ctx, ip);
564   _pfa   = pfa;
565   _error = error;
566   _space = spc;
567 }
568
569 PUBLIC inline
570 Mword
571 Tb_entry_pf::error() const
572 { return _error; }
573
574 PUBLIC inline
575 Address
576 Tb_entry_pf::pfa() const
577 { return _pfa; }
578
579 PUBLIC inline
580 Space*
581 Tb_entry_pf::space() const
582 { return _space; }
583
584
585 PUBLIC inline
586 void
587 Tb_entry_bp::set(Context const *ctx, Address ip,
588                  int mode, int len, Mword value, Address address)
589 {
590   set_global(Tbuf_breakpoint, ctx, ip);
591   _mode    = mode;
592   _len     = len;
593   _value   = value;
594   _address = address;
595 }
596
597
598
599 PUBLIC inline
600 int
601 Tb_entry_bp::mode() const
602 { return _mode; }
603
604 PUBLIC inline
605 int
606 Tb_entry_bp::len() const
607 { return _len; }
608
609 PUBLIC inline
610 Mword
611 Tb_entry_bp::value() const
612 { return _value; }
613
614 PUBLIC inline
615 Address
616 Tb_entry_bp::addr() const
617 { return _address; }
618
619
620 PUBLIC inline
621 void
622 Tb_entry_ke_bin::set(Context const *ctx, Address ip)
623 { set_global(Tbuf_ke_bin, ctx, ip); }
624
625 PUBLIC inline
626 void
627 Tb_entry_ke_bin::set_buf(unsigned i, char c)
628 {
629   if (i < sizeof(_msg)-1)
630     _msg[i] = c;
631 }
632