]> rtime.felk.cvut.cz Git - l4.git/blobdiff - kernel/fiasco/src/kern/tb_entry.cpp
update
[l4.git] / kernel / fiasco / src / kern / tb_entry.cpp
index 9a8afa34ed822b1405279042577b3a3100f5a504..f9dd6c67fe71e6175a0e22b4944239133134cd20 100644 (file)
@@ -5,24 +5,19 @@ INTERFACE:
 
 enum {
   Tbuf_unused             = 0,
-  Tbuf_pf                 = 1,
-  Tbuf_ipc                = 2,
-  Tbuf_ipc_res            = 3,
-  Tbuf_ipc_trace          = 4,
-  Tbuf_ke                 = 5,
-  Tbuf_ke_reg             = 6,
-  Tbuf_unmap              = 7,
-  Tbuf_shortcut_failed    = 8,
-  Tbuf_shortcut_succeeded = 9,
-  Tbuf_context_switch     = 10,
-  Tbuf_exregs             = 11,
-  Tbuf_breakpoint         = 12,
-  Tbuf_trap               = 13,
-  Tbuf_pf_res             = 14,
-  Tbuf_sched              = 15,
-  Tbuf_preemption         = 16,
-  Tbuf_ke_bin             = 17,
-  Tbuf_dynentries         = 18,
+  Tbuf_pf,
+  Tbuf_ipc,
+  Tbuf_ipc_res,
+  Tbuf_ipc_trace,
+  Tbuf_ke,
+  Tbuf_ke_reg,
+  Tbuf_exregs,
+  Tbuf_breakpoint,
+  Tbuf_pf_res,
+  Tbuf_preemption,
+  Tbuf_ke_bin,
+  Tbuf_dynentries,
+
   Tbuf_max                = 0x80,
   Tbuf_hidden             = 0x80,
 };
@@ -30,8 +25,12 @@ enum {
 #include "l4_types.h"
 
 class Tb_entry;
-
-typedef unsigned Tb_entry_formatter(Tb_entry *e, int max, char *buf);
+class Context;
+class Space;
+class Sched_context;
+class Syscall_frame;
+class Trap_state;
+class Tb_entry_formatter;
 
 struct Tb_log_table_entry
 {
@@ -41,15 +40,11 @@ struct Tb_log_table_entry
 };
 
 extern Tb_log_table_entry _log_table[];
-extern Tb_log_table_entry _log_table_end[];
+extern Tb_log_table_entry _log_table_end;
+
 
-class Context;
-class Space;
-class Sched_context;
-class Syscall_frame;
-class Trap_state;
 
-class Tb_entry_base
+class Tb_entry
 {
 protected:
   Mword                _number;        ///< event number
@@ -64,103 +59,148 @@ protected:
 
   static Mword (*rdcnt1)();
   static Mword (*rdcnt2)();
-} __attribute__((packed));
 
-class Tb_entry : public Tb_entry_base
-{
 public:
-  template<typename T>
-  class Payload_traits
+  class Group_order
   {
   public:
-    enum
-    {
-      Align  = __alignof__(T), //(sizeof(T) > sizeof(Mword)) ? sizeof(Mword) : sizeof(T),
-      Offset = sizeof(Tb_entry_base),
-      Payload_offset = ((Offset + Align -1) & ~(Align-1)) - Offset,
-      Total = Offset + Payload_offset + sizeof(T),
-    };
-
-    template<int I>
-    struct TTI
-    {};
-
-    static void tb_entry_size_mismatch(TTI<false> const &) {}
-    static void payload_too_big(TTI<false> const &) {}
-    static void payload_too_big()
-    {
-      tb_entry_size_mismatch(TTI<(sizeof(Tb_entry) != Tb_entry_size)>());
-      payload_too_big(TTI<((int)Total > (int)Tb_entry_size)>());
-    }
-
+    Group_order() : _o(0) {} // not grouped
+    Group_order(unsigned v) : _o(2 + v) {}
+    static Group_order none() { return Group_order(); }
+    static Group_order last() { return Group_order(255, true); }
+    static Group_order first() { return Group_order(0); }
+    static Group_order direct() { return Group_order(1, true); }
+
+    bool not_grouped() const { return _o == 0; }
+    bool is_direct() const { return _o == 1; }
+    bool is_first() const { return _o == 2; }
+    bool is_last() const { return _o == 255; }
+    bool grouped() const { return _o >= 2; }
+    unsigned char depth() const { return _o - 2; }
+
+  private:
+    Group_order(unsigned char v, bool) : _o(v) {}
+    unsigned char _o;
   };
 
+  Group_order has_partner() const { return Group_order::none(); }
+  Group_order is_partner(Tb_entry const *) const { return Group_order::none(); }
+  Mword partner() const { return 0; }
+
+} __attribute__((__packed__, __aligned__(8)));
+
+
+class Tb_entry_union : public Tb_entry
+{
 private:
-  template< typename T >
-  T *addr_of_payload() const
+  char _padding[Tb_entry_size - sizeof(Tb_entry)];
+};
+
+static_assert(sizeof(Tb_entry_union) == Tb_entry::Tb_entry_size,
+              "Tb_entry_union has the wrong size");
+
+struct Tb_entry_empty : public Tb_entry
+{
+  unsigned print(int, char *) const { return 0; }
+};
+
+class Tb_entry_formatter
+{
+public:
+  typedef Tb_entry::Group_order Group_order;
+
+  virtual unsigned print(Tb_entry const *e, int max, char *buf) const = 0;
+  virtual Group_order has_partner(Tb_entry const *e) const = 0;
+  virtual Group_order is_pair(Tb_entry const *e, Tb_entry const *n) const = 0;
+  virtual Mword partner(Tb_entry const *e) const = 0;
+
+  static Tb_entry_formatter const *get_fmt(Tb_entry const *e)
   {
-    Payload_traits<T>::payload_too_big();
+    if (e->type() >= Tbuf_dynentries)
+      return _log_table[e->type() - Tbuf_dynentries].fmt;
 
-    Address p = reinterpret_cast<Address>(_payload);
-    return reinterpret_cast<T*>(p + Payload_traits<T>::Payload_offset);
+    return _fixed[e->type()];
   }
 
+private:
+  static Tb_entry_formatter const *_fixed[];
+};
+
+
+template< typename T >
+class Tb_entry_formatter_t : public Tb_entry_formatter
+{
 public:
-  char _payload[Tb_entry_size-sizeof(Tb_entry_base)];
+  typedef T const *Const_ptr;
+  typedef T *Ptr;
 
-  template<typename T>
-  T *payload() { return addr_of_payload<T>(); }
-  
-  template<typename T>
-  T const *payload() const { return addr_of_payload<T>(); }
+  unsigned print(Tb_entry const *e, int max, char *buf) const
+  { return static_cast<Const_ptr>(e)->print(max, buf); }
 
+  Group_order has_partner(Tb_entry const *e) const
+  { return static_cast<Const_ptr>(e)->has_partner(); }
 
+  Group_order is_pair(Tb_entry const *e, Tb_entry const *n) const
+  {
+    //assert (get_fmt(e) == &singleton);
+
+    if (&singleton == get_fmt(n))
+      return static_cast<Const_ptr>(e)->is_partner(static_cast<Const_ptr>(n));
+    return Tb_entry::Group_order::none();
+  }
+
+  Mword partner(Tb_entry const *e) const
+  { return static_cast<Const_ptr>(e)->partner(); }
+
+  static Tb_entry_formatter_t const singleton;
 };
 
+template<typename T>
+Tb_entry_formatter_t<T> const Tb_entry_formatter_t<T>::singleton;
+
+
 /** logged ipc. */
 class Tb_entry_ipc : public Tb_entry
 {
 private:
-  struct Payload
-  {
-    L4_msg_tag _tag;           ///< message tag
-    Mword      _dword[2];      ///< first two message words
-    L4_obj_ref _dst;           ///< destination id
-    Mword       _dbg_id;
-    Mword       _label;
-    L4_timeout_pair _timeout;  ///< timeout
-  };
+  L4_msg_tag   _tag;           ///< message tag
+  Mword        _dword[2];      ///< first two message words
+  L4_obj_ref   _dst;           ///< destination id
+  Mword       _dbg_id;
+  Mword       _label;
+  L4_timeout_pair _timeout;    ///< timeout
+public:
+  Tb_entry_ipc() : _timeout(0) {}
+  unsigned print(int max, char *buf) const;
 };
 
 /** logged ipc result. */
 class Tb_entry_ipc_res : public Tb_entry
 {
 private:
-  struct Payload
-  {
-    L4_msg_tag _tag;           ///< message tag
-    Mword      _dword[2];      ///< first two dwords
-    L4_error   _result;        ///< result
-    Mword      _from;          ///< receive descriptor
-    Mword      _pair_event;    ///< referred event
-    Unsigned8  _have_snd;      ///< ipc had send part
-    Unsigned8  _is_np;         ///< next period bit set
-  };
+  L4_msg_tag   _tag;           ///< message tag
+  Mword        _dword[2];      ///< first two dwords
+  L4_error     _result;        ///< result
+  Mword        _from;          ///< receive descriptor
+  Mword        _pair_event;    ///< referred event
+  Unsigned8    _have_snd;      ///< ipc had send part
+  Unsigned8    _is_np;         ///< next period bit set
+public:
+  unsigned print(int max, char *buf) const;
 };
 
 /** logged ipc for user level tracing with Vampir. */
 class Tb_entry_ipc_trace : public Tb_entry
 {
 private:
-  struct Payload
-  {
-    Unsigned64 _snd_tsc;       ///< entry tsc
-    L4_msg_tag _result;        ///< result
-    L4_obj_ref _snd_dst;       ///< send destination
-    Mword      _rcv_dst;       ///< rcv partner
-    Unsigned8  _snd_desc;
-    Unsigned8  _rcv_desc;
-  };
+  Unsigned64   _snd_tsc;       ///< entry tsc
+  L4_msg_tag   _result;        ///< result
+  L4_obj_ref   _snd_dst;       ///< send destination
+  Mword        _rcv_dst;       ///< rcv partner
+  Unsigned8    _snd_desc;
+  Unsigned8    _rcv_desc;
+public:
+  unsigned print(int max, char *buf) const;
 };
 
 #if 0
@@ -179,95 +219,71 @@ private:
 class Tb_entry_pf : public Tb_entry
 {
 private:
-  struct Payload
-  {
-    Address    _pfa;           ///< pagefault address
-    Mword      _error;         ///< pagefault error code
-    Space      *_space;
-  };
+  Address      _pfa;           ///< pagefault address
+  Mword        _error;         ///< pagefault error code
+  Space        *_space;
+public:
+  unsigned print(int max, char *buf) const;
 };
 
 /** pagefault result. */
 class Tb_entry_pf_res : public Tb_entry
 {
 private:
-  struct Payload
-  {
-    Address    _pfa;
-    L4_error   _err;
-    L4_error   _ret;
-  };
+  Address      _pfa;
+  L4_error     _err;
+  L4_error     _ret;
+public:
+  unsigned print(int max, char *buf) const;
 };
 
 
 /** logged kernel event. */
-class Tb_entry_ke : public Tb_entry
+template<typename BASE, unsigned TAG>
+class Tb_entry_ke_t : public BASE
 {
-  enum { MSG_POINTER_PAYLOAD_OFFSET
-           = 5 - ((sizeof(Tb_entry_base) + 2 + 3) % sizeof(Mword)) };
-};
-
-/** logged breakpoint. */
-class Tb_entry_bp : public Tb_entry
-{
-private:
-  struct Payload
+protected:
+  union Msg
   {
-    Address    _address;       ///< breakpoint address
-    int                _len;           ///< breakpoint length
-    Mword      _value;         ///< value at address
-    int                _mode;          ///< breakpoint mode
-  } __attribute__((packed));
-};
+    char msg[BASE::Tb_entry_size - sizeof(BASE)];
+    struct Ptr
+    {
+      char tag[2];
+      char const *ptr;
+    } mptr;
+  } _msg;
+} __attribute__((__packed__));
+
+typedef Tb_entry_ke_t<Tb_entry, Tbuf_ke> Tb_entry_ke;
 
-/** logged context switch. */
-class Tb_entry_ctx_sw : public Tb_entry
+class Tb_entry_ke_reg_b : public Tb_entry
 {
-private:
-  struct Payload
-  {
-    Context const *_dst;               ///< switcher target
-    Context const *_dst_orig;
-    Address    _kernel_ip;
-    Mword      _lock_cnt;
-    Space      *_from_space;
-    Sched_context *_from_sched;
-    Mword      _from_prio;
-  } __attribute__((packed));
-};
+public:
+  Mword v[3];
+} __attribute__((__packed__));
 
-/** logged scheduling event. */
-class Tb_entry_sched : public Tb_entry
+class Tb_entry_ke_reg : public Tb_entry_ke_t<Tb_entry_ke_reg_b, Tbuf_ke_reg>
 {
-private:
-  struct Payload
-  {
-    unsigned short _mode;
-    Context const *_owner;
-    unsigned short _id;
-    unsigned short _prio;
-    signed long         _left;
-    unsigned long  _quantum;
-  } __attribute__((packed));
 };
 
-
-/** logged preemption */
-class Tb_entry_preemption : public Tb_entry
+/** logged breakpoint. */
+class Tb_entry_bp : public Tb_entry
 {
 private:
-  struct Payload
-  {
-    Mword       _preempter;
-  };
+  Address      _address;       ///< breakpoint address
+  int          _len;           ///< breakpoint length
+  Mword        _value;         ///< value at address
+  int          _mode;          ///< breakpoint mode
+public:
+  unsigned print(int max, char *buf) const;
 };
 
-
 /** logged binary kernel event. */
 class Tb_entry_ke_bin : public Tb_entry
 {
 public:
-  enum { SIZE = 31 };
+  char _msg[Tb_entry_size - sizeof(Tb_entry)];
+  enum { SIZE = 30 };
 };
 
 
@@ -284,10 +300,22 @@ IMPLEMENTATION:
 #include "trap_state.h"
 
 
-PROTECTED static Mword Tb_entry_base::dummy_read_pmc() { return 0; }
+PROTECTED static Mword Tb_entry::dummy_read_pmc() { return 0; }
 
-Mword (*Tb_entry_base::rdcnt1)() = dummy_read_pmc;
-Mword (*Tb_entry_base::rdcnt2)() = dummy_read_pmc;
+Mword (*Tb_entry::rdcnt1)() = dummy_read_pmc;
+Mword (*Tb_entry::rdcnt2)() = dummy_read_pmc;
+Tb_entry_formatter const *Tb_entry_formatter::_fixed[Tbuf_dynentries];
+
+
+PUBLIC static
+void
+Tb_entry_formatter::set_fixed(unsigned type, Tb_entry_formatter const *f)
+{
+  if (type >= Tbuf_dynentries)
+    return;
+
+  _fixed[type] = f;
+}
 
 
 PUBLIC static
@@ -306,93 +334,93 @@ Tb_entry::set_rdcnt(int num, Mword (*f)())
 
 PUBLIC inline
 void
-Tb_entry_base::clear()
+Tb_entry::clear()
 { _type = Tbuf_unused; }
 
 PUBLIC inline NEEDS["kip.h", "globals.h"]
 void
-Tb_entry_base::set_global(char type, Context const *ctx, Address ip)
+Tb_entry::set_global(char type, Context const *ctx, Address ip)
 {
   _type   = type;
   _ctx    = ctx;
   _ip     = ip;
   _kclock = (Unsigned32)Kip::k()->clock;
-  _cpu    = current_cpu();
+  _cpu    = cxx::int_value<Cpu_number>(current_cpu());
 }
 
 PUBLIC inline
 void
-Tb_entry_base::hide()
+Tb_entry::hide()
 { _type |= Tbuf_hidden; }
 
 PUBLIC inline
 void
-Tb_entry_base::unhide()
+Tb_entry::unhide()
 { _type &= ~Tbuf_hidden; }
 
 PUBLIC inline
 Address
-Tb_entry_base::ip() const
+Tb_entry::ip() const
 { return _ip; }
 
 PUBLIC inline
 Context const *
-Tb_entry_base::ctx() const
+Tb_entry::ctx() const
 { return _ctx; }
 
 PUBLIC inline
 Unsigned8
-Tb_entry_base::type() const
+Tb_entry::type() const
 { return _type & (Tbuf_max-1); }
 
 PUBLIC inline
 int
-Tb_entry_base::hidden() const
+Tb_entry::hidden() const
 { return _type & Tbuf_hidden; }
 
 PUBLIC inline
 Mword
-Tb_entry_base::number() const
+Tb_entry::number() const
 { return _number; }
 
 PUBLIC inline
 void
-Tb_entry_base::number(Mword number)
+Tb_entry::number(Mword number)
 { _number = number; }
 
 PUBLIC inline
 void
-Tb_entry_base::rdpmc1()
+Tb_entry::rdpmc1()
 { _pmc1 = rdcnt1(); }
 
 PUBLIC inline
 void
-Tb_entry_base::rdpmc2()
+Tb_entry::rdpmc2()
 { _pmc2 = rdcnt2(); }
 
 PUBLIC inline
 Unsigned32
-Tb_entry_base::kclock() const
+Tb_entry::kclock() const
 { return _kclock; }
 
 PUBLIC inline
 Unsigned8
-Tb_entry_base::cpu() const
+Tb_entry::cpu() const
 { return _cpu; }
 
 PUBLIC inline
 Unsigned64
-Tb_entry_base::tsc() const
+Tb_entry::tsc() const
 { return _tsc; }
 
 PUBLIC inline
 Unsigned32
-Tb_entry_base::pmc1() const
+Tb_entry::pmc1() const
 { return _pmc1; }
 
 PUBLIC inline
 Unsigned32
-Tb_entry_base::pmc2() const
+Tb_entry::pmc2() const
 { return _pmc2; }
 
 
@@ -402,89 +430,63 @@ Tb_entry_ipc::set(Context const *ctx, Mword ip, Syscall_frame *ipc_regs, Utcb *u
                  Mword dbg_id, Unsigned64 left)
 {
   set_global(Tbuf_ipc, ctx, ip);
-  Payload *p = payload<Payload>();
-  p->_dst       = ipc_regs->ref();
-  p->_label     = ipc_regs->from_spec();
-
+  _dst       = ipc_regs->ref();
+  _label     = ipc_regs->from_spec();
 
-  p->_dbg_id = dbg_id;
 
-  p->_timeout   = ipc_regs->timeout();
-  p->_tag       = ipc_regs->tag();
-  if (ipc_regs->next_period())
-    {
-      p->_dword[0]  = (Unsigned32)(left & 0xffffffff);
-      p->_dword[1]  = (Unsigned32)(left >> 32);
-    }
-  else
-    {
-      // hint for gcc
-      register Mword tmp0 = utcb->values[0];
-      register Mword tmp1 = utcb->values[1];
-      p->_dword[0]  = tmp0;
-      p->_dword[1]  = tmp1;
-    }
-}
+  _dbg_id = dbg_id;
 
-PUBLIC inline
-void
-Tb_entry_ipc::set_sc(Context const *ctx, Mword ip, Syscall_frame *ipc_regs,
-                     Utcb *utcb, Unsigned64 left)
-{
-  set_global(Tbuf_shortcut_succeeded, ctx, ip);
-  Payload *p = payload<Payload>();
-  p->_dst       = ipc_regs->ref();
-  p->_timeout   = ipc_regs->timeout();
+  _timeout   = ipc_regs->timeout();
+  _tag       = ipc_regs->tag();
   if (ipc_regs->next_period())
     {
-      p->_dword[0]  = (Unsigned32)(left & 0xffffffff);
-      p->_dword[1]  = (Unsigned32)(left >> 32);
+      _dword[0]  = (Unsigned32)(left & 0xffffffff);
+      _dword[1]  = (Unsigned32)(left >> 32);
     }
   else
     {
       // hint for gcc
       register Mword tmp0 = utcb->values[0];
       register Mword tmp1 = utcb->values[1];
-      p->_dword[0]  = tmp0;
-      p->_dword[1]  = tmp1;
+      _dword[0]  = tmp0;
+      _dword[1]  = tmp1;
     }
 }
 
-
 PUBLIC inline
 Mword
 Tb_entry_ipc::ipc_type() const
-{ return payload<Payload>()->_dst.flags(); }
+{ return _dst.op(); }
 
 PUBLIC inline
 Mword
 Tb_entry_ipc::dbg_id() const
-{ return payload<Payload>()->_dbg_id; }
+{ return _dbg_id; }
 
 PUBLIC inline
 L4_obj_ref
 Tb_entry_ipc::dst() const
-{ return payload<Payload>()->_dst; }
+{ return _dst; }
 
 PUBLIC inline
 L4_timeout_pair
 Tb_entry_ipc::timeout() const
-{ return payload<Payload>()->_timeout; }
+{ return _timeout; }
 
 PUBLIC inline
 L4_msg_tag
 Tb_entry_ipc::tag() const
-{ return payload<Payload>()->_tag; }
+{ return _tag; }
 
 PUBLIC inline
 Mword
 Tb_entry_ipc::label() const
-{ return payload<Payload>()->_label; }
+{ return _label; }
 
 PUBLIC inline
 Mword
 Tb_entry_ipc::dword(unsigned index) const
-{ return payload<Payload>()->_dword[index]; }
+{ return _dword[index]; }
 
 
 PUBLIC inline NEEDS ["entry_frame.h"]
@@ -495,54 +497,53 @@ Tb_entry_ipc_res::set(Context const *ctx, Mword ip, Syscall_frame *ipc_regs,
                      Unsigned8 is_np)
 {
   set_global(Tbuf_ipc_res, ctx, ip);
-  Payload *p = payload<Payload>();
   // hint for gcc
   register Mword tmp0 = utcb->values[0];
   register Mword tmp1 = utcb->values[1];
-  p->_dword[0]   = tmp0;
-  p->_dword[1]   = tmp1;
-  p->_tag        = ipc_regs->tag();
-  p->_pair_event = pair_event;
-  p->_result     = L4_error::from_raw(result);
-  p->_from       = ipc_regs->from_spec();
-  p->_have_snd   = have_snd;
-  p->_is_np      = is_np;
+  _dword[0]   = tmp0;
+  _dword[1]   = tmp1;
+  _tag        = ipc_regs->tag();
+  _pair_event = pair_event;
+  _result     = L4_error::from_raw(result);
+  _from       = ipc_regs->from_spec();
+  _have_snd   = have_snd;
+  _is_np      = is_np;
 }
 
 PUBLIC inline
 int
 Tb_entry_ipc_res::have_snd() const
-{ return payload<Payload>()->_have_snd; }
+{ return _have_snd; }
 
 PUBLIC inline
 int
 Tb_entry_ipc_res::is_np() const
-{ return payload<Payload>()->_is_np; }
+{ return _is_np; }
 
 PUBLIC inline
 Mword
 Tb_entry_ipc_res::from() const
-{ return payload<Payload>()->_from; }
+{ return _from; }
 
 PUBLIC inline
 L4_error
 Tb_entry_ipc_res::result() const
-{ return payload<Payload>()->_result; }
+{ return _result; }
 
 PUBLIC inline
 L4_msg_tag
 Tb_entry_ipc_res::tag() const
-{ return payload<Payload>()->_tag; }
+{ return _tag; }
 
 PUBLIC inline
 Mword
 Tb_entry_ipc_res::dword(unsigned index) const
-{ return payload<Payload>()->_dword[index]; }
+{ return _dword[index]; }
 
 PUBLIC inline
 Mword
 Tb_entry_ipc_res::pair_event() const
-{ return payload<Payload>()->_pair_event; }
+{ return _pair_event; }
 
 
 PUBLIC inline
@@ -553,103 +554,39 @@ Tb_entry_ipc_trace::set(Context const *ctx, Mword ip, Unsigned64 snd_tsc,
                        Unsigned8 rcv_desc)
 {
   set_global(Tbuf_ipc_trace, ctx, ip);
-  payload<Payload>()->_snd_tsc  = snd_tsc;
-  payload<Payload>()->_snd_dst  = snd_dst;
-  payload<Payload>()->_rcv_dst  = rcv_dst;
-  payload<Payload>()->_result   = result;
-  payload<Payload>()->_snd_desc = snd_desc;
-  payload<Payload>()->_rcv_desc = rcv_desc;
+  _snd_tsc  = snd_tsc;
+  _snd_dst  = snd_dst;
+  _rcv_dst  = rcv_dst;
+  _result   = result;
+  _snd_desc = snd_desc;
+  _rcv_desc = rcv_desc;
 }
 
-#if 0
-PUBLIC inline
-void
-Tb_entry_ipc_sfl::set(Context *ctx, Mword ip,
-                     Global_id from,
-                     L4_timeout_pair timeout, Global_id dst,
-                     Unsigned8 is_irq, Unsigned8 snd_lst,
-                     Unsigned8 dst_ok, Unsigned8 dst_lck,
-                     Unsigned8 preempt)
-{
-  set_global(Tbuf_shortcut_failed, ctx, ip);
-  Payload *p = payload<Payload>();
-  p->_from      = from;
-  p->_timeout   = timeout;
-  p->_dst       = dst;
-  p->_is_irq    = is_irq;
-  p->_snd_lst   = snd_lst;
-  p->_dst_ok    = dst_ok;
-  p->_dst_lck   = dst_lck;
-  p->_preempt   = preempt;
-}
-
-PUBLIC inline
-L4_timeout_pair
-Tb_entry_ipc_sfl::timeout() const
-{ return _timeout; }
-
-PUBLIC inline
-Global_id
-Tb_entry_ipc_sfl::from() const
-{ return _from; }
-
-PUBLIC inline
-Global_id
-Tb_entry_ipc_sfl::dst() const
-{ return _dst; }
-
-PUBLIC inline
-Unsigned8
-Tb_entry_ipc_sfl::is_irq() const
-{ return _is_irq; }
-
-PUBLIC inline
-Unsigned8
-Tb_entry_ipc_sfl::snd_lst() const
-{ return _snd_lst; }
-
-PUBLIC inline
-Unsigned8
-Tb_entry_ipc_sfl::dst_ok() const
-{ return _dst_ok; }
-
-PUBLIC inline
-Unsigned8
-Tb_entry_ipc_sfl::dst_lck() const
-{ return _dst_lck; }
-
-PUBLIC inline
-Unsigned8
-Tb_entry_ipc_sfl::preempt() const
-{ return _preempt; }
-#endif
-
 PUBLIC inline
 void
 Tb_entry_pf::set(Context const *ctx, Address ip, Address pfa,
                 Mword error, Space *spc)
 {
   set_global(Tbuf_pf, ctx, ip);
-  Payload *p = payload<Payload>();
-  p->_pfa   = pfa;
-  p->_error = error;
-  p->_space = spc;
+  _pfa   = pfa;
+  _error = error;
+  _space = spc;
 }
 
 PUBLIC inline
 Mword
 Tb_entry_pf::error() const
-{ return payload<Payload>()->_error; }
+{ return _error; }
 
 PUBLIC inline
 Address
 Tb_entry_pf::pfa() const
-{ return payload<Payload>()->_pfa; }
+{ return _pfa; }
 
 PUBLIC inline
 Space*
 Tb_entry_pf::space() const
-{ return payload<Payload>()->_space; }
+{ return _space; }
 
 
 PUBLIC inline
@@ -658,26 +595,25 @@ Tb_entry_pf_res::set(Context const *ctx, Address ip, Address pfa,
                     L4_error err, L4_error ret)
 {
   set_global(Tbuf_pf_res, ctx, ip);
-  Payload *p = payload<Payload>();
-  p->_pfa = pfa;
-  p->_err = err;
-  p->_ret = ret;
+  _pfa = pfa;
+  _err = err;
+  _ret = ret;
 }
 
 PUBLIC inline
 Address
 Tb_entry_pf_res::pfa() const
-{ return payload<Payload>()->_pfa; }
+{ return _pfa; }
 
 PUBLIC inline
 L4_error
 Tb_entry_pf_res::err() const
-{ return payload<Payload>()->_err; }
+{ return _err; }
 
 PUBLIC inline
 L4_error
 Tb_entry_pf_res::ret() const
-{ return payload<Payload>()->_ret; }
+{ return _ret; }
 
 
 PUBLIC inline
@@ -686,10 +622,10 @@ Tb_entry_bp::set(Context const *ctx, Address ip,
                 int mode, int len, Mword value, Address address)
 {
   set_global(Tbuf_breakpoint, ctx, ip);
-  payload<Payload>()->_mode    = mode;
-  payload<Payload>()->_len     = len;
-  payload<Payload>()->_value   = value;
-  payload<Payload>()->_address = address;
+  _mode    = mode;
+  _len     = len;
+  _value   = value;
+  _address = address;
 }
 
 
@@ -697,181 +633,62 @@ Tb_entry_bp::set(Context const *ctx, Address ip,
 PUBLIC inline
 int
 Tb_entry_bp::mode() const
-{ return payload<Payload>()->_mode; }
+{ return _mode; }
 
 PUBLIC inline
 int
 Tb_entry_bp::len() const
-{ return payload<Payload>()->_len; }
+{ return _len; }
 
 PUBLIC inline
 Mword
 Tb_entry_bp::value() const
-{ return payload<Payload>()->_value; }
+{ return _value; }
 
 PUBLIC inline
 Address
 Tb_entry_bp::addr() const
-{ return payload<Payload>()->_address; }
+{ return _address; }
 
 
 
-PUBLIC inline
+PUBLIC template<typename BASE, unsigned TAG> inline
 void
-Tb_entry_ke::set(Context const *ctx, Address ip)
-{ set_global(Tbuf_ke, ctx, ip); }
+Tb_entry_ke_t<BASE, TAG>::set(Context const *ctx, Address ip)
+{ this->set_global(TAG, ctx, ip); }
 
-PUBLIC inline
+PUBLIC template<typename BASE, unsigned TAG> inline
 void
-Tb_entry_ke::set_const(Context const *ctx, Address ip, const char * const msg)
+Tb_entry_ke_t<BASE, TAG>::set_const(Context const *ctx, Address ip, char const *msg)
 {
-  set_global(Tbuf_ke, ctx, ip);
-  char *_msg = payload<char>();
-  _msg[0] = 0; _msg[1] = 1;
-  *(char const ** const)(_msg + MSG_POINTER_PAYLOAD_OFFSET) = msg;
+  this->set_global(TAG, ctx, ip);
+  _msg.mptr.tag[0] = 0;
+  _msg.mptr.tag[1] = 1;
+  _msg.mptr.ptr = msg;
 }
 
-PUBLIC inline
+PUBLIC template<typename BASE, unsigned TAG> inline
 void
-Tb_entry_ke::set_buf(unsigned i, char c)
+Tb_entry_ke_t<BASE, TAG>::set_buf(unsigned i, char c)
 {
-  char *_msg = payload<char>();
-  if (i < sizeof(_payload)-1)
-    _msg[i] = c >= ' ' ? c : '.';
+  if (i < sizeof(_msg.msg)-1)
+    _msg.msg[i] = c >= ' ' ? c : '.';
 }
 
-PUBLIC inline
+PUBLIC template<typename BASE, unsigned TAG> inline
 void
-Tb_entry_ke::term_buf(unsigned i)
+Tb_entry_ke_t<BASE, TAG>::term_buf(unsigned i)
 {
-  char *_msg = payload<char>();
-  _msg[i < sizeof(_payload)-1 ? i : sizeof(_payload)-1] = '\0';
+  _msg.msg[i < sizeof(_msg.msg)-1 ? i : sizeof(_msg.msg)-1] = '\0';
 }
 
-PUBLIC inline
-const char *
-Tb_entry_ke::msg() const
+PUBLIC template<typename BASE, unsigned TAG> inline
+char const *
+Tb_entry_ke_t<BASE, TAG>::msg() const
 {
-  char const *_msg = payload<char>();
-  return _msg[0] == 0 && _msg[1] == 1
-    ? *(char const ** const)(_msg + MSG_POINTER_PAYLOAD_OFFSET) : _msg;
-}
-
-
-PUBLIC inline
-void
-Tb_entry_ctx_sw::set(Context const *ctx, Space *from_space, Address ip,
-                    Context const *dst, Context const *dst_orig,
-                    Mword lock_cnt,
-                    Sched_context *from_sched, Mword from_prio,
-                    Address kernel_ip)
-{
-  set_global(Tbuf_context_switch, ctx, ip);
-  payload<Payload>()->_kernel_ip = kernel_ip;
-  payload<Payload>()->_dst        = dst;
-  payload<Payload>()->_dst_orig   = dst_orig;
-  payload<Payload>()->_lock_cnt   = lock_cnt;
-  payload<Payload>()->_from_space = from_space;
-  payload<Payload>()->_from_sched = from_sched;
-  payload<Payload>()->_from_prio  = from_prio;
-}
-
-PUBLIC inline
-Space*
-Tb_entry_ctx_sw::from_space() const
-{ return payload<Payload>()->_from_space; }
-
-PUBLIC inline
-Address
-Tb_entry_ctx_sw::kernel_ip() const
-{ return payload<Payload>()->_kernel_ip; }
-
-PUBLIC inline
-Mword
-Tb_entry_ctx_sw::lock_cnt() const
-{ return payload<Payload>()->_lock_cnt; }
-
-PUBLIC inline
-Context const *
-Tb_entry_ctx_sw::dst() const
-{ return payload<Payload>()->_dst; }
-
-PUBLIC inline
-Context const *
-Tb_entry_ctx_sw::dst_orig() const
-{ return payload<Payload>()->_dst_orig; }
-
-PUBLIC inline
-Mword
-Tb_entry_ctx_sw::from_prio() const
-{ return payload<Payload>()->_from_prio; }
-
-PUBLIC inline
-Sched_context*
-Tb_entry_ctx_sw::from_sched() const
-{ return payload<Payload>()->_from_sched; }
-
-PUBLIC inline
-void
-Tb_entry_sched::set (Context const *ctx, Address ip, unsigned short mode,
-                     Context const *owner, unsigned short id, unsigned short prio,
-                     signed long left, unsigned long quantum)
-{
-  set_global (Tbuf_sched, ctx, ip);
-  payload<Payload>()->_mode    = mode;
-  payload<Payload>()->_owner   = owner;
-  payload<Payload>()->_id      = id;
-  payload<Payload>()->_prio    = prio;
-  payload<Payload>()->_left    = left;
-  payload<Payload>()->_quantum = quantum;
+  return _msg.mptr.tag[0] == 0 && _msg.mptr.tag[1] == 1 ? _msg.mptr.ptr : _msg.msg;
 }
 
-PUBLIC inline
-unsigned short
-Tb_entry_sched::mode() const
-{ return payload<Payload>()->_mode; }
-
-PUBLIC inline
-Context const *
-Tb_entry_sched::owner() const
-{ return payload<Payload>()->_owner; }
-
-PUBLIC inline
-unsigned short
-Tb_entry_sched::id() const
-{ return payload<Payload>()->_id; }
-
-PUBLIC inline
-unsigned short
-Tb_entry_sched::prio() const
-{ return payload<Payload>()->_prio; }
-
-PUBLIC inline
-unsigned long
-Tb_entry_sched::quantum() const
-{ return payload<Payload>()->_quantum; }
-
-PUBLIC inline
-signed long
-Tb_entry_sched::left() const
-{ return payload<Payload>()->_left; }
-
-PUBLIC inline
-void
-Tb_entry_preemption::set (Context const *ctx, Mword preempter,
-                          Address ip)
-{
-  set_global (Tbuf_preemption, ctx, ip);
-  payload<Payload>()->_preempter = preempter;
-};
-
-PUBLIC inline
-Mword
-Tb_entry_preemption::preempter() const
-{ return payload<Payload>()->_preempter; }
-
-
-
 PUBLIC inline
 void
 Tb_entry_ke_bin::set(Context const *ctx, Address ip)
@@ -881,7 +698,19 @@ PUBLIC inline
 void
 Tb_entry_ke_bin::set_buf(unsigned i, char c)
 {
-  char *_bin = payload<char>();
-  if (i < sizeof(_payload)-1)
-    _bin[i] = c;
+  if (i < sizeof(_msg)-1)
+    _msg[i] = c;
+}
+
+PUBLIC inline
+void
+Tb_entry_ke_reg::set_const(Context const *ctx, Mword eip,
+                           const char *msg,
+                           Mword v1, Mword v2, Mword v3)
+{
+  Tb_entry_ke_t<Tb_entry_ke_reg_b, Tbuf_ke_reg>::set_const(ctx, eip, msg);
+  v[0] = v1;
+  v[1] = v2;
+  v[2] = v3;
 }
+