#ifndef __L4__IA32__TRACEBUFFER_H__
#define __L4__IA32__TRACEBUFFER_H__
#if defined(TRACEBUFFER)
#include <l4/types.h>
typedef struct {
L4_Word32_t cycles;
L4_Word32_t pmc0;
L4_Word32_t pmc1;
} L4_Tracestatus_t;
typedef struct {
L4_Tracestatus_t status;
L4_Word32_t identifier;
L4_Word32_t data[4];
} L4_Trace_t;
typedef struct {
L4_Word32_t current;
L4_Word32_t magic;
L4_Word32_t counter;
L4_Word32_t threshold;
L4_Word32_t pad[4];
L4_Trace_t trace[];
} L4_Tracebuffer_t;
extern L4_Tracebuffer_t * L4_Tracebuffer;
#define L4_TBUF_MAGIC 0x20121977
#if defined(PERFMON)
#define __L4_RDPMC "rdpmc\n"
#else
#define __L4_RDPMC "xor %%eax, %%eax\n"
#endif
#define __L4_TBUF_GET_NEXT_RECORD(addr) \
asm volatile ( \
" movl %%fs:0, %%esi \n" \
" addl $32, %%esi \n" \
" movl %%esi, %%edi \n" \
" andl $0x1fffff, %%esi \n" \
" movl %%esi, %%fs:0 \n" \
" rdtsc \n" \
" movl %%eax, %%fs:0(%%edi) \n" \
" xor %%ecx, %%ecx \n" \
__L4_RDPMC \
" movl %%eax, %%fs:4(%%edi) \n" \
" inc %%ecx \n" \
__L4_RDPMC \
" movl %%eax, %%fs:8(%%edi) \n" \
:"=D" (addr) \
: \
:"eax", "ecx", "edx", "esi")
#define __L4_TBUF_STORE_ITEM(addr, offset, item) \
asm volatile ("movl %0, %%fs:(" #offset "*4+12)(%%edi)" \
: \
:"r" (item), "D" (addr))
L4_INLINE void L4_TBUF_RECORD_EVENT (unsigned _id)
{
unsigned addr;
__L4_TBUF_GET_NEXT_RECORD (addr);
__L4_TBUF_STORE_ITEM (addr, 0, _id & 0x7FFFFFFF);
}
L4_INLINE void L4_TBUF_RECORD_EVENT_1 (unsigned _id,
unsigned _p0)
{
unsigned addr;
__L4_TBUF_GET_NEXT_RECORD (addr);
__L4_TBUF_STORE_ITEM (addr, 0, _id & 0x7FFFFFFF);
__L4_TBUF_STORE_ITEM (addr, 1, _p0);
}
L4_INLINE void L4_TBUF_RECORD_EVENT_2 (unsigned _id,
unsigned _p0,
unsigned _p1)
{
unsigned addr;
__L4_TBUF_GET_NEXT_RECORD (addr);
__L4_TBUF_STORE_ITEM (addr, 0, _id & 0x7FFFFFFF);
__L4_TBUF_STORE_ITEM (addr, 1, _p0);
__L4_TBUF_STORE_ITEM (addr, 2, _p1);
}
L4_INLINE void L4_TBUF_RECORD_EVENT_3 (unsigned _id,
unsigned _p0,
unsigned _p1,
unsigned _p2)
{
unsigned addr;
__L4_TBUF_GET_NEXT_RECORD (addr);
__L4_TBUF_STORE_ITEM (addr, 0, _id & 0x7FFFFFFF);
__L4_TBUF_STORE_ITEM (addr, 1, _p0);
__L4_TBUF_STORE_ITEM (addr, 2, _p1);
__L4_TBUF_STORE_ITEM (addr, 3, _p2);
}
L4_INLINE void L4_TBUF_RECORD_EVENT_4 (unsigned _id,
unsigned _p0,
unsigned _p1,
unsigned _p2,
unsigned _p3)
{
unsigned addr;
__L4_TBUF_GET_NEXT_RECORD (addr);
__L4_TBUF_STORE_ITEM (addr, 0, _id & 0x7FFFFFFF);
__L4_TBUF_STORE_ITEM (addr, 1, _p0);
__L4_TBUF_STORE_ITEM (addr, 2, _p1);
__L4_TBUF_STORE_ITEM (addr, 3, _p2);
__L4_TBUF_STORE_ITEM (addr, 4, _p3);
}
#if defined(__cplusplus)
L4_INLINE void L4_TBUF_RECORD_EVENT (unsigned _id, unsigned _p0)
{
L4_TBUF_RECORD_EVENT_1 (_id, _p0);
}
L4_INLINE void L4_TBUF_RECORD_EVENT (unsigned _id,
unsigned _p0,
unsigned _p1)
{
L4_TBUF_RECORD_EVENT_2 (_id, _p0, _p1);
}
L4_INLINE void L4_TBUF_RECORD_EVENT (unsigned _id,
unsigned _p0,
unsigned _p1,
unsigned _p2)
{
L4_TBUF_RECORD_EVENT_3 (_id, _p0, _p1, _p2);
}
L4_INLINE void L4_TBUF_RECORD_EVENT (unsigned _id,
unsigned _p0,
unsigned _p1,
unsigned _p2,
unsigned _p3)
{
L4_TBUF_RECORD_EVENT_4 (_id, _p0, _p1, _p2, _p3);
}
#endif
#define L4_TBUF_INCREMENT_TRACE_COUNTER() \
asm volatile ( \
" movl %%fs:8, %%edx \n" \
" movl %%fs:12, %%edi \n" \
" inc %%edx \n" \
" movl %%edx, %%fs:8 \n" \
" cmpl %%edx, %%edi \n" \
" jge 1f \n" \
" int3 \n" \
" xor %%edx, %%edx \n" \
" movl %%edx, %%fs:8 \n" \
"1: \n" \
: \
: \
:"edx", "edi")
#define L4_TBUF_CLEAR_BUFFER() \
asm volatile ("movl $0, %fs:0")
#else
#define L4_TBUF_RECORD_EVENT(args...)
#define L4_TBUF_RECORD_EVENT_1(args...)
#define L4_TBUF_RECORD_EVENT_2(args...)
#define L4_TBUF_RECORD_EVENT_3(args...)
#define L4_TBUF_RECORD_EVENT_4(args...)
#define L4_TBUF_INCREMENT_TRACE_COUNTER()
#define L4_TBUF_CLEAR_BUFFER()
#endif
#endif