mirror of https://github.com/l4ka/pistachio.git
Added a non-ASM implementation of the tracebuffer for X86 and PPC
kernels. User to follow soon.
This commit is contained in:
parent
497dc5e8d3
commit
32b08ecb1c
|
@ -386,7 +386,6 @@ menu trace
|
|||
TBUF_PERFMON_ENERGY
|
||||
X86_KEEP_LAST_BRANCHES
|
||||
|
||||
unless ARCH_X86 suppress dependent TRACEBUFFER
|
||||
when X_EVT_LOGGING suppress TBUF_PERFMON TBUF_PERFMON_ENERGY
|
||||
unless TRACEBUFFER and PERFMON suppress TBUF_PERFMON
|
||||
unless TBUF_PERFMON and SUBARCH_X32 and CPU_X86_P4 suppress TBUF_PERFMON_ENERGY
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
##
|
||||
## Copyright (C) 2010, Karlsruhe University
|
||||
##
|
||||
## File path: generic/Makeconf
|
||||
## File path: kdb/generic/Makeconf
|
||||
## Description: Generic linkser script for x86.
|
||||
##
|
||||
## Redistribution and use in source and binary forms, with or without
|
||||
|
@ -40,7 +40,12 @@ SOURCES+= kdb/generic/bootinfo.cc \
|
|||
kdb/generic/memdump.cc \
|
||||
kdb/generic/print.cc \
|
||||
kdb/generic/tid_format.cc \
|
||||
kdb/generic/tracepoints.cc \
|
||||
kdb/generic/tracepoints.cc
|
||||
|
||||
|
||||
ifeq ("$(CONFIG_TRACEBUFFER)","y")
|
||||
SOURCES+= kdb/generic/tracebuffer.cc
|
||||
endif
|
||||
|
||||
ifeq ("$(CONFIG_X86_IO_FLEXPAGES)","y")
|
||||
SOURCES+= kdb/generic/vrt.cc
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
* Copyright (C) 2002-2003, 2007-2010, Karlsruhe University
|
||||
*
|
||||
* File path: kdb/glue/v4-x86/tracebuffer.cc
|
||||
* File path: kdb/generic/tracebuffer.cc
|
||||
* Description: Tracebuffer for PC99 platform
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -27,6 +27,8 @@
|
|||
* SUCH DAMAGE.
|
||||
*
|
||||
********************************************************************/
|
||||
|
||||
#if defined(CONFIG_TRACEBUFFER)
|
||||
#include <debug.h>
|
||||
#include <linear_ptab.h>
|
||||
#include <generic/lib.h>
|
||||
|
@ -36,9 +38,7 @@
|
|||
#include <kdb/tracebuffer.h>
|
||||
#include INC_API(thread.h)
|
||||
#include INC_API(tcb.h)
|
||||
#include INC_GLUE(timer.h)
|
||||
|
||||
#if defined(CONFIG_TRACEBUFFER)
|
||||
#include INC_GLUE(schedule.h)
|
||||
|
||||
FEATURESTRING ("tracebuffer");
|
||||
|
||||
|
@ -138,8 +138,10 @@ private:
|
|||
if (tsc == 0) return true;
|
||||
|
||||
u64_t ttsc = t->tsc;
|
||||
#if defined(CONFIG_TBUF_PERFMON_ENERGY)
|
||||
if (get_tbuf_config().pmon_e)
|
||||
ttsc <<= X86_PMC_TSC_SHIFT;
|
||||
#endif
|
||||
return (ttsc >= tsc);
|
||||
}
|
||||
|
||||
|
@ -447,9 +449,9 @@ public:
|
|||
{
|
||||
u64_t pmcdelta0;
|
||||
u64_t pmcdelta1;
|
||||
#if defined(CONFIG_TBUF_PERFMON_ENERGY)
|
||||
if (get_tbuf_config().pmon_e)
|
||||
{
|
||||
|
||||
// Energy mix
|
||||
c_delta <<= X86_PMC_TSC_SHIFT;
|
||||
|
||||
|
@ -468,6 +470,7 @@ public:
|
|||
pmcdelta1 = p_delta / 1000;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// User and kernel instructions
|
||||
pmcdelta0 = pmc_delta(rec->pmc0, (word_t) old[cpu].pmc0);
|
||||
|
@ -626,7 +629,10 @@ void tbuf_dump (word_t count, word_t usec, word_t tp_id, word_t cpumask)
|
|||
|
||||
if (usec)
|
||||
{
|
||||
u64_t tsc = x86_rdtsc() - ((u64_t) usec * (u64_t) (get_timer()->get_proc_freq() / 1000));
|
||||
procdesc_t * pdesc = get_kip()->processor_info.get_procdesc(get_current_cpu());
|
||||
ASSERT (pdesc);
|
||||
word_t freq = pdesc->internal_freq + 1;
|
||||
u64_t tsc = get_cpu_cycles() - ((u64_t) usec * (u64_t) (freq / 1000));
|
||||
count = size;
|
||||
tbuf_handler.set_tsc(tsc);
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
######################################################################
|
||||
##
|
||||
## Copyright (C) 2007-2009, Karlsruhe University
|
||||
## Copyright (C) 2007-2010, Karlsruhe University
|
||||
##
|
||||
## File path: kdb/glue/v4-x86/Makeconf
|
||||
## Description:
|
||||
|
@ -14,10 +14,6 @@ SOURCES+= kdb/glue/v4-x86/thread.cc kdb/glue/v4-x86/prepost.cc \
|
|||
kdb/glue/v4-x86/readmem.cc kdb/glue/v4-x86/resources.cc \
|
||||
kdb/glue/v4-x86/addrtranslation.cc
|
||||
|
||||
ifeq ("$(CONFIG_TRACEBUFFER)","y")
|
||||
SOURCES+= kdb/glue/v4-x86/tracebuffer.cc
|
||||
endif
|
||||
|
||||
ifeq ("$(CONFIG_X_CTRLXFER_MSG)","y")
|
||||
SOURCES+= kdb/glue/v4-x86/ipc.cc
|
||||
endif
|
||||
|
|
|
@ -55,7 +55,6 @@ private:
|
|||
public:
|
||||
static word_t count;
|
||||
static cpu_t * get(cpuid_t cpuid) {
|
||||
ASSERT(cpuid < CONFIG_SMP_MAX_CPUS);
|
||||
return &descriptors[cpuid];
|
||||
}
|
||||
|
||||
|
@ -67,4 +66,11 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
INLINE cpuid_t get_current_cpu()
|
||||
{
|
||||
extern cpuid_t current_cpu;
|
||||
return current_cpu;
|
||||
}
|
||||
|
||||
|
||||
#endif /* !__API__V4__CPU_H__ */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*********************************************************************
|
||||
*
|
||||
* Copyright (C) 2002-2004, 2006, 2008-2009, Karlsruhe University
|
||||
* Copyright (C) 2002-2004, 2006, 2008-2010, Karlsruhe University
|
||||
*
|
||||
* File path: api/v4/smp.cc
|
||||
* Description: Multiprocessor handling for cross-processor
|
||||
|
@ -30,14 +30,16 @@
|
|||
* $Id: smp.cc,v 1.10 2006/06/16 10:28:44 stoess Exp $
|
||||
*
|
||||
********************************************************************/
|
||||
#if defined(CONFIG_SMP)
|
||||
|
||||
#include <sync.h>
|
||||
#include <kdb/tracepoints.h>
|
||||
#include INC_API(smp.h)
|
||||
#include INC_API(schedule.h)
|
||||
#include INC_API(queueing.h)
|
||||
|
||||
cpuid_t current_cpu UNIT("cpulocal");;
|
||||
|
||||
#if defined(CONFIG_SMP)
|
||||
|
||||
//#define TRACE_IPI(x...) do { printf("CPU %d: ", get_current_cpu()); printf(x); } while(0)
|
||||
|
||||
#if defined(CONFIG_SMP_SYNC_REQUEST)
|
||||
|
|
|
@ -790,12 +790,7 @@ INLINE space_t * get_current_space()
|
|||
return get_current_tcb()->get_space();
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SMP
|
||||
INLINE cpuid_t get_current_cpu()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_SMP)
|
||||
INLINE bool tcb_t::migrate_to_processor(cpuid_t processor)
|
||||
{
|
||||
return processor == 0;
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/*********************************************************************
|
||||
*
|
||||
* Copyright (C) 2002-2004, 2006-2008, 2010, Karlsruhe University
|
||||
*
|
||||
* File path: arch/powerpc/tracebuffer.h
|
||||
* Description: PPC specific tracebuffer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
********************************************************************/
|
||||
#pragma once
|
||||
#include <tcb_layout.h>
|
||||
#include INC_ARCH(ppc_registers.h)
|
||||
|
||||
#define TRACEBUFFER_SIZE ( 1 * 1024 * 1024)
|
||||
INLINE void tracerecord_t::store_arch(const traceconfig_t config)
|
||||
{
|
||||
tsc = ppc_get_timebase();
|
||||
|
||||
}
|
||||
|
||||
INLINE void tracebuffer_t::initialize()
|
||||
{
|
||||
magic = TRACEBUFFER_MAGIC;
|
||||
current = 0;
|
||||
mask = TBUF_DEFAULT_MASK;
|
||||
max = (TRACEBUFFER_SIZE/sizeof(tracerecord_t))-1;
|
||||
config.raw = 0;
|
||||
#if defined(CONFIG_SMP)
|
||||
config.smp = 1;
|
||||
#endif
|
||||
#if defined(CONFIG_TBUF_PERFMON)
|
||||
config.pmon = 1;
|
||||
#endif
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/*********************************************************************
|
||||
*
|
||||
* Copyright (C) 2007, 2009, Karlsruhe University
|
||||
* Copyright (C) 2007, 2009-2010, Karlsruhe University
|
||||
*
|
||||
* File path: arch/x86/atomic.h
|
||||
* Description:
|
||||
|
@ -33,7 +33,7 @@ public:
|
|||
__asm__ __volatile__(X86_LOCK "sub $1, %0" : "=m"(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
word_t operator = (word_t val)
|
||||
{ return this->val = val; }
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Copyright (C) 2002-2004, 2006-2008, 2010, Karlsruhe University
|
||||
*
|
||||
* File path: arch/x86/tracebuffer.h
|
||||
* Description: IA32 specific tracebuffer
|
||||
* Description: X86 specific tracebuffer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
|
@ -31,247 +31,118 @@
|
|||
#ifndef __ARCH__X86__TRACEBUFFER_H__
|
||||
#define __ARCH__X86__TRACEBUFFER_H__
|
||||
|
||||
#include INC_ARCH_SA(tracebuffer.h)
|
||||
#include INC_ARCH(cpu.h)
|
||||
#include <tcb_layout.h>
|
||||
|
||||
#if defined(CONFIG_IS_32BIT)
|
||||
#define TRACEBUFFER_PGENTSZ pgent_t::size_4m
|
||||
#else
|
||||
#define TRACEBUFFER_PGENTSZ pgent_t::size_2m
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(CONFIG_TBUF_PERFMON_ENERGY)
|
||||
#define TRACEBUFFER_SIZE (32 * 1024 * 1024)
|
||||
#else
|
||||
#define TRACEBUFFER_SIZE ( 4 * 1024 * 1024)
|
||||
#endif
|
||||
/**
|
||||
* A tracebuffer record indicates the type of event, the time of the
|
||||
* event, the current thread, a number of event specific parameters,
|
||||
* and potentially the current performance counters.
|
||||
*/
|
||||
class tracerecord_t
|
||||
|
||||
/**********************************************************************
|
||||
* Sample PMC energy weights
|
||||
**********************************************************************/
|
||||
#if 0
|
||||
/* P4 */
|
||||
#define X86_PMC_TSC_WEIGHT (617)
|
||||
#define X86_PMC_UC_WEIGHT (712)
|
||||
#define X86_PMC_MQW_WEIGHT (475)
|
||||
#define X86_PMC_RB_WEIGHT (56)
|
||||
#define X86_PMC_MB_WEIGHT (34046)
|
||||
#define X86_PMC_MR_WEIGHT (173)
|
||||
#define X86_PMC_MLR_WEIGHT (2996)
|
||||
#define X86_PMC_LDM_WEIGHT (1355)
|
||||
#else
|
||||
/* Pentium D */
|
||||
#define X86_PMC_TSC_WEIGHT (1418)
|
||||
#define X86_PMC_UC_WEIGHT (1285)
|
||||
#define X86_PMC_LDM_WEIGHT (881)
|
||||
#define X86_PMC_MR_WEIGHT (649)
|
||||
#define X86_PMC_MB_WEIGHT (23421)
|
||||
#define X86_PMC_MLR_WEIGHT (4320)
|
||||
#define X86_PMC_RB_WEIGHT (840)
|
||||
#define X86_PMC_MQW_WEIGHT (75)
|
||||
#endif
|
||||
|
||||
#define X86_PMC_TSC_SHIFT 6
|
||||
#define X86_PMC_UC (0)
|
||||
#define X86_PMC_MLR (1)
|
||||
#define X86_PMC_MQW (4)
|
||||
#define X86_PMC_RB (5)
|
||||
#define X86_PMC_MB (12)
|
||||
#define X86_PMC_MR (13)
|
||||
#define X86_PMC_LDM (14)
|
||||
|
||||
INLINE void tracerecord_t::store_arch(const traceconfig_t config)
|
||||
{
|
||||
public:
|
||||
static const word_t num_args = 9;
|
||||
|
||||
struct {
|
||||
word_t utype : 16;
|
||||
word_t ktype : 16;
|
||||
word_t : BITS_WORD-32;
|
||||
word_t cpu : 16;
|
||||
word_t id : 16;
|
||||
word_t : BITS_WORD-32;
|
||||
};
|
||||
word_t tsc;
|
||||
word_t thread;
|
||||
word_t pmc0;
|
||||
word_t pmc1;
|
||||
const char * str;
|
||||
word_t arg[num_args];
|
||||
|
||||
bool is_kernel_event (void) { return ktype && ! utype; }
|
||||
word_t get_type (void) { return (utype == 0) ? ktype : utype; }
|
||||
|
||||
friend class kdb_t;
|
||||
tsc = x86_rdtsc();
|
||||
|
||||
};
|
||||
|
||||
|
||||
union traceconfig_t
|
||||
{
|
||||
struct {
|
||||
word_t smp : 1; // SMP
|
||||
word_t pmon : 1; // Enable perf monitoring
|
||||
word_t pmon_cpu : 2; // CPU: 00=P2/P3/K8, 01=P4
|
||||
word_t pmon_e : 2; // Enable energy monitoring
|
||||
word_t : BITS_WORD-6;
|
||||
};
|
||||
word_t raw;
|
||||
};
|
||||
|
||||
/**
|
||||
* The tracebuffer is a region in memory accessible by kernel and user
|
||||
* through the FS segment. The first words of the region indicate the
|
||||
* current tracebuffer record and which events should be recorded.
|
||||
* The remaining part of the region hold the counters and the
|
||||
* tracebuffer records.
|
||||
*/
|
||||
class tracebuffer_t
|
||||
{
|
||||
word_t magic;
|
||||
word_t current;
|
||||
word_t mask;
|
||||
word_t sizemask;
|
||||
traceconfig_t config;
|
||||
word_t __pad[3];
|
||||
word_t counters[8];
|
||||
tracerecord_t tracerecords[];
|
||||
|
||||
public:
|
||||
|
||||
enum offset_e
|
||||
if (config.pmon)
|
||||
{
|
||||
ofs_counters = sizeof(word_t) * 8,
|
||||
};
|
||||
|
||||
void initialize (void)
|
||||
switch (config.pmon_cpu)
|
||||
{
|
||||
magic = TRACEBUFFER_MAGIC;
|
||||
current = 0;
|
||||
mask = TBUF_DEFAULT_MASK;
|
||||
sizemask = TRACEBUFFER_SIZE-1;
|
||||
config.raw = 0;
|
||||
case 0:
|
||||
// P2/P3/K8
|
||||
pmc0 = x86_rdpmc(0);
|
||||
pmc1 = x86_rdpmc(1);
|
||||
break;
|
||||
case 1:
|
||||
// P4
|
||||
if (config.pmon_e)
|
||||
{
|
||||
u64_t pmce =
|
||||
X86_PMC_TSC_WEIGHT * x86_rdtsc() +
|
||||
X86_PMC_UC_WEIGHT * x86_rdpmc(X86_PMC_UC) +
|
||||
X86_PMC_MLR_WEIGHT * x86_rdpmc(X86_PMC_MLR) +
|
||||
X86_PMC_MQW_WEIGHT * x86_rdpmc(X86_PMC_MQW) +
|
||||
X86_PMC_RB_WEIGHT * x86_rdpmc(X86_PMC_RB) +
|
||||
X86_PMC_MB_WEIGHT * x86_rdpmc(X86_PMC_MB) +
|
||||
X86_PMC_MR_WEIGHT * x86_rdpmc(X86_PMC_MR) +
|
||||
X86_PMC_LDM_WEIGHT * x86_rdpmc(X86_PMC_LDM);
|
||||
|
||||
pmc0 = (word_t) pmce;
|
||||
pmc1 = (word_t) (pmce >> 32);
|
||||
}
|
||||
else
|
||||
{
|
||||
pmc0 = (word_t) x86_rdpmc(12);
|
||||
pmc1 = (word_t) x86_rdpmc(2);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
INLINE void tracebuffer_t::initialize()
|
||||
{
|
||||
magic = TRACEBUFFER_MAGIC;
|
||||
current = 0;
|
||||
mask = TBUF_DEFAULT_MASK;
|
||||
max = (TRACEBUFFER_SIZE/sizeof(tracerecord_t))-1;
|
||||
config.raw = 0;
|
||||
#if defined(CONFIG_SMP)
|
||||
config.smp = 1;
|
||||
config.smp = 1;
|
||||
#endif
|
||||
#if defined(CONFIG_TBUF_PERFMON)
|
||||
config.pmon = 1;
|
||||
config.pmon = 1;
|
||||
#endif
|
||||
#if defined(CONFIG_TBUF_PERFMON_ENERGY)
|
||||
config.pmon_e = 1;
|
||||
config.pmon_e = 1;
|
||||
#endif
|
||||
#if defined(CONFIG_CPU_X86_P4)
|
||||
config.pmon_cpu = 1;
|
||||
config.pmon_cpu = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool is_valid (void) { return magic == TRACEBUFFER_MAGIC; }
|
||||
|
||||
friend class tbuf_handler_t;
|
||||
};
|
||||
|
||||
INLINE tracebuffer_t * get_tracebuffer (void)
|
||||
{
|
||||
extern tracebuffer_t * tracebuffer;
|
||||
return tracebuffer;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Access to performance monitoring counters
|
||||
*/
|
||||
|
||||
# define TBUF_PMC_SEL_0_686 " xor %1, %1 \n"
|
||||
# define TBUF_PMC_SEL_1_686 " mov $1, %1 \n"
|
||||
|
||||
/* PMC_MSR_IQ_COUNTER 0 and 2 */
|
||||
# define TBUF_PMC_SEL_0_P4 " mov $12, %1 \n"
|
||||
# define TBUF_PMC_SEL_1_P4 " add $ 2, %1 \n"
|
||||
|
||||
/**
|
||||
* Start recording new event into tracebuffer.
|
||||
*
|
||||
* @param event type of event
|
||||
*
|
||||
* @returns index to current event record
|
||||
*/
|
||||
|
||||
#define TBUF_GET_NEXT_RECORD(type, id) \
|
||||
({ \
|
||||
word_t dummy, addr; \
|
||||
asm volatile ( \
|
||||
/* Check wheter to filter the event */ \
|
||||
" mov %%fs:2*%c9, %3 \n" \
|
||||
" and %1, %3 \n" \
|
||||
" jz 7f \n" \
|
||||
" or %2, %1 \n" \
|
||||
\
|
||||
\
|
||||
/* Get record offset into EDI */ \
|
||||
"1: mov %%fs:1*%c9, %3 \n" \
|
||||
" mov %8, %0 \n" \
|
||||
" mov %0, %2 \n" \
|
||||
" add %3, %0 \n" \
|
||||
" and $"MKSTR(TRACEBUFFER_SIZE-1)", %0\n" \
|
||||
" cmovz %2, %0 \n" \
|
||||
" testl $1, %%fs:4*%c9 \n" \
|
||||
" jz 2f \n" \
|
||||
" lock; \n" \
|
||||
"2: \n" \
|
||||
" cmpxchg %0, %%fs:1*%c9 \n" \
|
||||
" jnz 1b \n" \
|
||||
\
|
||||
/* Store type, cpu, id, thread, counters */ \
|
||||
" mov %1, %2 \n" \
|
||||
" xorw %%cx, %%cx \n" \
|
||||
" movl %%ecx, %%fs:(%0) \n" \
|
||||
" shl $16, %%edx \n" \
|
||||
" mov __idle_tcb, %3 \n" \
|
||||
" movw "MKSTR(OFS_TCB_CPU)"(%3), %%dx \n" \
|
||||
" movl %%edx, %%fs:1*%c9(%0) \n" \
|
||||
TBUF_RDPMCS \
|
||||
TBUF_SP \
|
||||
"7: \n" \
|
||||
: \
|
||||
"=D" (addr), /* 0 */ \
|
||||
"=c" (dummy), /* 1 */ \
|
||||
"=d" (dummy), /* 2 */ \
|
||||
"=a" (dummy) /* 3 */ \
|
||||
: \
|
||||
"0" (0), /* 4 */ \
|
||||
"1" ((type & 0xffff)<<16), /* 5 */ \
|
||||
"2" (id & 0xffff), /* 6 */ \
|
||||
"3" (0), /* 7 */ \
|
||||
"i" (sizeof (tracerecord_t)), /* 8 */ \
|
||||
"i" (sizeof(word_t)) /* 9 */ \
|
||||
); \
|
||||
addr; \
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Increase a tracebuffer counter.
|
||||
*
|
||||
* @param ctr counter number
|
||||
*/
|
||||
#define TBUF_INCREASE_COUNTER(ctr) \
|
||||
do { \
|
||||
asm volatile ( \
|
||||
" testl $1, %%fs:4*%c1 \n" \
|
||||
" jz 2f \n" \
|
||||
" lock; \n" \
|
||||
" inc %%fs:8*%c1(%0) \n" \
|
||||
: \
|
||||
: \
|
||||
"r" ((ctr & 0x7) * 4), \
|
||||
"i" (sizeof(word_t))); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/**
|
||||
* Record item into event buffer at indicated location.
|
||||
*
|
||||
* @param addr offset of event record
|
||||
* @param offset string to be recorded
|
||||
*/
|
||||
#define TBUF_STORE_STR(addr, str) \
|
||||
do { \
|
||||
asm volatile ( \
|
||||
"mov %0, %%fs:6*%c2(%1)\n" \
|
||||
: \
|
||||
: \
|
||||
"r" (str), \
|
||||
"D" (addr), \
|
||||
"i" (sizeof(word_t))); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/**
|
||||
* Record arguments into event buffer at indicated location.
|
||||
*
|
||||
* @param addr offset of event record
|
||||
* @param offset offset within event record
|
||||
* @param item value to be recorded
|
||||
*/
|
||||
#define TBUF_STORE_DATA(addr, offset, item) \
|
||||
do { \
|
||||
word_t dummy; \
|
||||
asm volatile ( \
|
||||
"mov %2, %%fs:(%1)\n" \
|
||||
: \
|
||||
"=D" (dummy) \
|
||||
: \
|
||||
"0" (addr + (7 + offset) * sizeof(word_t)), \
|
||||
"r" (item)); \
|
||||
} while (0)
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* !__ARCH__X86__TRACEBUFFER_H__ */
|
||||
|
|
|
@ -1,152 +0,0 @@
|
|||
/*********************************************************************
|
||||
*
|
||||
* Copyright (C) 2002-2004, 2006-2008, 2010, Karlsruhe University
|
||||
*
|
||||
* File path: arch/x86/x32/tracebuffer.h
|
||||
* Description: IA32 specific tracebuffer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
********************************************************************/
|
||||
#ifndef __ARCH__X86__X32__TRACEBUFFER_H__
|
||||
#define __ARCH__X86__X32__TRACEBUFFER_H__
|
||||
|
||||
#include <tcb_layout.h>
|
||||
|
||||
#define TRACEBUFFER_MAGIC 0x143acebf
|
||||
#define TRACEBUFFER_PGENTSZ pgent_t::size_4m
|
||||
|
||||
|
||||
/*
|
||||
* Access to stack pointer, timestamp, and performance monitoring counters
|
||||
*/
|
||||
|
||||
#define TBUF_SP " mov %%esp, %%fs:3*%c9(%0) \n" \
|
||||
|
||||
|
||||
/* Registers:
|
||||
* EAX unused
|
||||
* EBX unused, not preserved
|
||||
* ECX unused
|
||||
* EDX unused
|
||||
* ESI unused, not preserved
|
||||
* EDI TB record address
|
||||
* EBP unused, not preserved
|
||||
*/
|
||||
|
||||
/**********************************************************************
|
||||
* Sample PMC energy weights
|
||||
**********************************************************************/
|
||||
#if 0
|
||||
/* P4 */
|
||||
#define X86_PMC_TSC_WEIGHT (617)
|
||||
#define X86_PMC_UC_WEIGHT (712)
|
||||
#define X86_PMC_MQW_WEIGHT (475)
|
||||
#define X86_PMC_RB_WEIGHT (56)
|
||||
#define X86_PMC_MB_WEIGHT (34046)
|
||||
#define X86_PMC_MR_WEIGHT (173)
|
||||
#define X86_PMC_MLR_WEIGHT (2996)
|
||||
#define X86_PMC_LDM_WEIGHT (1355)
|
||||
#else
|
||||
/* Pentium D */
|
||||
#define X86_PMC_TSC_WEIGHT (1418)
|
||||
#define X86_PMC_UC_WEIGHT (1285)
|
||||
#define X86_PMC_LDM_WEIGHT (881)
|
||||
#define X86_PMC_MR_WEIGHT (649)
|
||||
#define X86_PMC_MB_WEIGHT (23421)
|
||||
#define X86_PMC_MLR_WEIGHT (4320)
|
||||
#define X86_PMC_RB_WEIGHT (840)
|
||||
#define X86_PMC_MQW_WEIGHT (75)
|
||||
#endif
|
||||
|
||||
#define X86_PMC_TSC (0)
|
||||
#define X86_PMC_TSC_SHIFT 6
|
||||
#define X86_PMC_UC (0)
|
||||
#define X86_PMC_RB (5)
|
||||
#define X86_PMC_MR (13)
|
||||
#define X86_PMC_LDM (14)
|
||||
|
||||
#define TBUF_RDPMC_WEIGHTED(nr, weight, op) \
|
||||
" mov $"MKSTR(nr)", %%ecx \n" /* select pmc */ \
|
||||
" "#op" \n" /* pmc/tsc in %edx:%eax */ \
|
||||
" mov %%edx, %%esi \n" /* save pmc_hi */ \
|
||||
" mov $"MKSTR(weight)", %%ecx \n" /* load weight */ \
|
||||
" mul %%ecx \n" /* r1 = pmc_lo * weight */ \
|
||||
" mov %%edx, %%ebx \n" /* save r1_hi */ \
|
||||
" xchg %%eax, %%ecx \n" /* r1_lo <-> weight */ \
|
||||
" mul %%esi \n" /* r2 = weight * pmc_hi */ \
|
||||
" add %%ebx, %%eax \n" /* r2_lo += r1_hi */ \
|
||||
" addl %%ecx, %%fs:4*%c9(%0) \n" /* result_lo */ \
|
||||
" adcl %%eax, %%fs:5*%c9(%0) \n" /* result_hi */
|
||||
|
||||
|
||||
|
||||
#define TBUF_RDPMCS \
|
||||
/* Get config into rbx/ebx */ \
|
||||
" push %%ebx \n" /* save ebx */ \
|
||||
" movl %%fs:4*%c9, %%ebx \n" \
|
||||
" test $2, %%ebx \n" \
|
||||
" jz 5f \n" /* no pmon, rdtsc only */ \
|
||||
" test $4, %%ebx \n" \
|
||||
" jz 4f \n" /* P2/K8 pmon */ \
|
||||
" test $8, %%ebx \n" \
|
||||
" jz 3f \n" /* P4 pmon */ \
|
||||
/* P4 PerfMon Energy */ \
|
||||
" push %%ebx \n" /* save ebx */ \
|
||||
" push %%esi \n" /* save esi */ \
|
||||
" movl $0, %%fs:4*%c9(%0) \n" /* result_lo */ \
|
||||
" movl $0, %%fs:5*%c9(%0) \n" /* result_hi */ \
|
||||
TBUF_RDPMC_WEIGHTED(X86_PMC_UC, X86_PMC_UC_WEIGHT, rdpmc) \
|
||||
TBUF_RDPMC_WEIGHTED(X86_PMC_RB, X86_PMC_RB_WEIGHT, rdpmc) \
|
||||
TBUF_RDPMC_WEIGHTED(X86_PMC_MR, X86_PMC_MR_WEIGHT, rdpmc) \
|
||||
TBUF_RDPMC_WEIGHTED(X86_PMC_LDM, X86_PMC_LDM_WEIGHT, rdpmc) \
|
||||
TBUF_RDPMC_WEIGHTED(X86_PMC_TSC, X86_PMC_TSC_WEIGHT, rdtsc) \
|
||||
" pop %%esi \n" /* restore esi */ \
|
||||
" pop %%ebx \n" /* restore ebx */ \
|
||||
" rdtsc \n" \
|
||||
" shrd $"MKSTR(X86_PMC_TSC_SHIFT)", %%edx, %%eax\n" \
|
||||
" mov %%eax, %%fs:2*%c9(%0) \n" \
|
||||
" jmp 6f \n" \
|
||||
"3: \n" \
|
||||
/* P4 PerfMon */ \
|
||||
" mov $12, %1 \n" \
|
||||
" rdpmc \n" \
|
||||
" movl %%eax, %%fs:4*%c9(%0) \n" \
|
||||
" add $2, %1 \n" \
|
||||
" rdpmc \n" \
|
||||
" movl %%eax, %%fs:5*%c9(%0) \n" \
|
||||
" jmp 5f \n" \
|
||||
"4: \n" \
|
||||
/* P2/K8 PerfMon */ \
|
||||
" xor %1, %1 \n" \
|
||||
" rdpmc \n" \
|
||||
" movl %%eax, %%fs:4*%c9(%0) \n" \
|
||||
" mov $1, %1 \n" \
|
||||
" rdpmc \n" \
|
||||
" movl %%eax, %%fs:5*%c9(%0) \n" \
|
||||
"5: \n" \
|
||||
" rdtsc \n" \
|
||||
" mov %%eax, %%fs:2*%c9(%0) \n" \
|
||||
"6: \n" \
|
||||
" pop %%ebx \n" /* restore ebx */ \
|
||||
|
||||
#endif /* !__ARCH__X86__X32__TRACEBUFFER_H__ */
|
|
@ -1,6 +1,6 @@
|
|||
/*********************************************************************
|
||||
*
|
||||
* Copyright (C) 2002-2008, Karlsruhe University
|
||||
* Copyright (C) 2002-2008, 2010, Karlsruhe University
|
||||
*
|
||||
* File path: arch/x86/x64/ptab.h
|
||||
* Description: X86-64 pagetable management (4KByte long mode)
|
||||
|
@ -52,7 +52,8 @@ class x86_pgent_t
|
|||
public:
|
||||
enum pagesize_e {
|
||||
size_4k = 0,
|
||||
size_2m = 1
|
||||
size_2m = 1,
|
||||
size_superpage = 1
|
||||
};
|
||||
|
||||
// predicates
|
||||
|
|
|
@ -1,89 +0,0 @@
|
|||
/*********************************************************************
|
||||
*
|
||||
* Copyright (C) 2002-2004, 2006-2008, 2010, Karlsruhe University
|
||||
*
|
||||
* File path: arch/x86/x64/tracebuffer.h
|
||||
* Description: Functions for accessing the tracebuffer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
********************************************************************/
|
||||
#ifndef __ARCH__X86__X64__TRACEBUFFER_H__
|
||||
#define __ARCH__X86__X64__TRACEBUFFER_H__
|
||||
|
||||
#include <tcb_layout.h>
|
||||
|
||||
#define TRACEBUFFER_MAGIC 0x1464b123acebf
|
||||
#define TRACEBUFFER_PGENTSZ pgent_t::size_2m
|
||||
|
||||
/*
|
||||
* Access to stack pointer, timestamp, and performance monitoring counters
|
||||
*/
|
||||
|
||||
#define TBUF_SP " mov %%rsp, %%fs:3*%c9(%0) \n"
|
||||
|
||||
#define X86_PMC_TSC_SHIFT 0
|
||||
|
||||
#include INC_ARCH(tracebuffer.h)
|
||||
|
||||
#define TBUF_RDPMCS \
|
||||
/* Get config into rbx/ebx */ \
|
||||
" push %%rbx \n" /* save ebx */ \
|
||||
" movq %%fs:4*%c9, %%rbx \n" \
|
||||
" test $2, %%rbx \n" \
|
||||
" jz 4f \n" /* no pmon, rdtsc only */ \
|
||||
" test $4, %%rbx \n" \
|
||||
" jz 3f \n" /* P2/K8 pmon */ \
|
||||
/* P4 PerfMon */ \
|
||||
" mov $12, %1 \n" \
|
||||
" rdpmc \n" \
|
||||
" shl $32, %%rdx \n" \
|
||||
" movl %%eax, %%edx \n" \
|
||||
" mov %2, %%fs:4*%c9(%0) \n" \
|
||||
" add $2, %1 \n" \
|
||||
" rdpmc \n" \
|
||||
" shl $32, %%rdx \n" \
|
||||
" movl %%eax, %%edx \n" \
|
||||
" mov %2, %%fs:5*%c9(%0) \n" \
|
||||
" jmp 4f \n" \
|
||||
"3: \n" \
|
||||
/* P2/K8 PerfMon */ \
|
||||
" xor %1, %1 \n" \
|
||||
" rdpmc \n" \
|
||||
" shl $32, %%rdx \n" \
|
||||
" movl %%eax, %%edx \n" \
|
||||
" mov %2, %%fs:4*%c9(%0) \n" \
|
||||
" mov $1, %1 \n" \
|
||||
" rdpmc \n" \
|
||||
" shl $32, %%rdx \n" \
|
||||
" movl %%eax, %%edx \n" \
|
||||
" mov %2, %%fs:5*%c9(%0) \n" \
|
||||
"4: \n" \
|
||||
" rdtsc \n" \
|
||||
" shl $32, %%rdx \n" \
|
||||
" movl %%eax, %%edx \n" \
|
||||
" mov %2, %%fs:2*%c9(%0) \n" \
|
||||
" pop %%rbx \n" /* restore ebx */ \
|
||||
|
||||
|
||||
|
||||
#endif /* !__ARCH__X86__X64__TRACEBUFFER_H__ */
|
|
@ -1,6 +1,6 @@
|
|||
/*********************************************************************
|
||||
*
|
||||
* Copyright (C) 2002-2005, 2007-2008, Karlsruhe University
|
||||
* Copyright (C) 2002-2005, 2007-2008, 2010, Karlsruhe University
|
||||
*
|
||||
* File path: arch/x86/x64/tss.h
|
||||
* Description: AMD64 Task State Segment
|
||||
|
|
|
@ -371,6 +371,16 @@ static SECTION(SEC_INIT) void perfmon_init( void )
|
|||
ppc_set_pmc4( 0 );
|
||||
}
|
||||
}
|
||||
#if defined(CONFIG_TRACEBUFFER)
|
||||
tracebuffer_t * tracebuffer;
|
||||
EXTERN_KMEM_GROUP (kmem_misc);
|
||||
|
||||
void SECTION(SEC_INIT) setup_tracebuffer (void)
|
||||
{
|
||||
tracebuffer = (tracebuffer_t *) kmem.alloc (kmem_misc, TRACEBUFFER_SIZE);
|
||||
tracebuffer->initialize ();
|
||||
}
|
||||
#endif /* CONFIG_TRACEBUFFER */
|
||||
|
||||
static SECTION(SEC_INIT) void timer_start( void )
|
||||
{
|
||||
|
@ -676,6 +686,12 @@ extern "C" void SECTION(SEC_INIT) startup_system ( word_t r3, word_t r4, word_t
|
|||
TRACE_INIT("Initializing boot CPU\n");
|
||||
cpu_init( 0 );
|
||||
|
||||
#if defined(CONFIG_TRACEBUFFER)
|
||||
/* allocate and setup tracebuffer */
|
||||
TRACE_INIT("Initializing Tracebuffer (%dM)\n", TRACEBUFFER_SIZE / (1024 * 1024));
|
||||
setup_tracebuffer();
|
||||
#endif
|
||||
|
||||
TRACE_INIT("Initializing kernel debugger\n");
|
||||
if( get_kip()->kdebug_init )
|
||||
get_kip()->kdebug_init();
|
||||
|
|
|
@ -183,6 +183,9 @@ void SECTION(".init.memory") space_t::init_cpu_mappings(cpuid_t cpu)
|
|||
init_swtlb[idx].tlb1.raw, init_swtlb[idx].tlb2.raw);
|
||||
}
|
||||
}
|
||||
|
||||
current_cpu = cpu;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,6 @@ DECLARE_KMEM_GROUP (kmem_utcb);
|
|||
|
||||
space_t * kernel_space = NULL;
|
||||
addr_t utcb_page = NULL;
|
||||
cpuid_t current_cpu UNIT("x86.cpulocal");;
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
|
@ -617,7 +616,7 @@ bool space_t::sync_io_bitmap()
|
|||
#if defined(CONFIG_SMP)
|
||||
/* May be that we've already created a bitmap on a different cpu */
|
||||
|
||||
if (current_cpu == data.reference_ptab)
|
||||
if (get_current_cpu() == data.reference_ptab)
|
||||
return false;
|
||||
|
||||
if (get_io_bitmap() != get_io_bitmap(data.reference_ptab))
|
||||
|
@ -860,7 +859,9 @@ void SECTION (".init") space_t::init_cpu_mappings(cpuid_t cpu)
|
|||
get_top_pdir_phys(cpu), cpu);
|
||||
x86_mmu_t::set_active_pagetable((word_t)get_top_pdir_phys(cpu));
|
||||
x86_mmu_t::flush_tlb(true);
|
||||
#if defined(CONFIG_SMP)
|
||||
current_cpu = cpu;
|
||||
#endif
|
||||
TRACE_INIT("\tCPU local pagetable activated %x (CPU %d)\n",
|
||||
x86_mmu_t::get_active_pagetable(), cpu);
|
||||
#endif
|
||||
|
|
|
@ -221,20 +221,5 @@ INLINE void tcb_t::release_copy_area (void)
|
|||
resources.release_copy_area (this, true);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* global tcb functions
|
||||
*
|
||||
**********************************************************************/
|
||||
|
||||
#if defined(CONFIG_SMP)
|
||||
extern cpuid_t current_cpu;
|
||||
INLINE cpuid_t get_current_cpu()
|
||||
{
|
||||
return current_cpu;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif /* !__GLUE__V4_X86__TCB_H__ */
|
||||
|
|
|
@ -34,9 +34,148 @@
|
|||
|
||||
|
||||
#if defined(CONFIG_TRACEBUFFER)
|
||||
#include INC_API(cpu.h)
|
||||
#include INC_ARCH(atomic.h)
|
||||
|
||||
typedef u16_t cpuid_t;
|
||||
|
||||
#define TB_DEFAULT (1 << 0)
|
||||
#define TB_USERID_START (100)
|
||||
|
||||
#if defined(CONFIG_IS_32BIT)
|
||||
#define TRACEBUFFER_MAGIC 0x1464b123
|
||||
#else
|
||||
#define TRACEBUFFER_MAGIC 0x1464b123acebf
|
||||
#endif
|
||||
|
||||
union traceconfig_t
|
||||
{
|
||||
struct {
|
||||
word_t smp : 1; // SMP
|
||||
word_t pmon : 1; // Enable perf monitoring
|
||||
word_t pmon_cpu : 2; // CPU: x86: 00=P2/P3/K8, 01=P4
|
||||
word_t pmon_e : 2; // Enable energy monitoring
|
||||
word_t : BITS_WORD-6;
|
||||
};
|
||||
word_t raw;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A tracebuffer record indicates the type of event, the time of the
|
||||
* event, the current thread, a number of event specific parameters,
|
||||
* and potentially the current performance counters.
|
||||
*/
|
||||
class tracerecord_t
|
||||
{
|
||||
public:
|
||||
static const word_t num_args = 9;
|
||||
|
||||
struct {
|
||||
word_t utype : 16;
|
||||
word_t ktype : 16;
|
||||
word_t : BITS_WORD-32;
|
||||
word_t cpu : 16;
|
||||
word_t id : 16;
|
||||
word_t : BITS_WORD-32;
|
||||
};
|
||||
word_t tsc;
|
||||
word_t thread;
|
||||
word_t pmc0;
|
||||
word_t pmc1;
|
||||
const char * str;
|
||||
word_t arg[num_args];
|
||||
|
||||
bool is_kernel_event (void) { return ktype && ! utype; }
|
||||
word_t get_type (void) { return (utype == 0) ? ktype : utype; }
|
||||
|
||||
friend class kdb_t;
|
||||
|
||||
void store_arch(const traceconfig_t config);
|
||||
|
||||
public:
|
||||
|
||||
void store_record(const traceconfig_t config, word_t type, word_t id)
|
||||
{
|
||||
/* Store type, cpu, id, thread, counters */
|
||||
ktype = type;
|
||||
utype = 0;
|
||||
id = id;
|
||||
cpu = get_current_cpu();
|
||||
thread = (word_t) __builtin_frame_address(0);
|
||||
store_arch(config);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The tracebuffer is a region in memory accessible by kernel and user
|
||||
* through the FS segment. The first words of the region indicate the
|
||||
* current tracebuffer record and which events should be recorded.
|
||||
* The remaining part of the region hold the counters and the
|
||||
* tracebuffer records.
|
||||
*/
|
||||
class tracebuffer_t
|
||||
{
|
||||
word_t magic;
|
||||
atomic_t current;
|
||||
word_t mask;
|
||||
word_t max;
|
||||
traceconfig_t config;
|
||||
word_t __pad[3];
|
||||
word_t counters[8];
|
||||
tracerecord_t tracerecords[];
|
||||
|
||||
public:
|
||||
friend class tbuf_handler_t;
|
||||
|
||||
enum offset_e
|
||||
{
|
||||
ofs_counters = sizeof(word_t) * 8,
|
||||
};
|
||||
|
||||
void initialize();
|
||||
|
||||
bool is_valid (void) { return magic == TRACEBUFFER_MAGIC; }
|
||||
|
||||
bool next_record(word_t type, word_t id)
|
||||
{
|
||||
if (!this)
|
||||
return false;
|
||||
|
||||
/* Check wheter to filter the event */
|
||||
if ((mask & ((type & 0xffff) << 16)) == 0)
|
||||
return false;
|
||||
|
||||
current++;
|
||||
if (current == max)
|
||||
current = 0;
|
||||
|
||||
/* Store type, cpu, id, thread, counters */
|
||||
tracerecords[current].store_record(config, type, id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void increase_counter(word_t ctr)
|
||||
{
|
||||
counters[ctr & 0x7]++;
|
||||
}
|
||||
|
||||
void store_string(const char *str)
|
||||
{ tracerecords[current].str = str; }
|
||||
|
||||
void store_data(word_t offset, word_t item)
|
||||
{ tracerecords[current].arg[offset] = item; }
|
||||
|
||||
};
|
||||
|
||||
INLINE tracebuffer_t * get_tracebuffer (void)
|
||||
{
|
||||
extern tracebuffer_t * tracebuffer;
|
||||
return tracebuffer;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wrap tracepoint events with event type arguments
|
||||
*/
|
||||
|
@ -53,11 +192,6 @@ extern void tbuf_dump (word_t count, word_t usec, word_t tp_id = 0, word_t cpuma
|
|||
#include INC_ARCH(tracebuffer.h)
|
||||
#include <stdarg.h> /* for va_list, ... comes with gcc */
|
||||
|
||||
INLINE void tbuf_inc_counter (word_t counter)
|
||||
{
|
||||
TBUF_INCREASE_COUNTER (counter);
|
||||
}
|
||||
|
||||
#define tbuf_record_event(type, tpid, str, args...) \
|
||||
__tbuf_record_event(type, tpid, str, ##args, TRACEBUFFER_MAGIC);
|
||||
|
||||
|
@ -67,12 +201,11 @@ INLINE void __tbuf_record_event(word_t type, word_t tpid, const char *str, ...)
|
|||
va_list args;
|
||||
word_t arg;
|
||||
|
||||
word_t addr = TBUF_GET_NEXT_RECORD (type, tpid);
|
||||
|
||||
if (addr == 0)
|
||||
return;
|
||||
|
||||
TBUF_STORE_STR (addr, str);
|
||||
tracebuffer_t *tbuf = get_tracebuffer();
|
||||
if(!tbuf->next_record(type, tpid))
|
||||
return;
|
||||
|
||||
tbuf->store_string(str);
|
||||
|
||||
va_start(args, str);
|
||||
|
||||
|
@ -83,7 +216,7 @@ INLINE void __tbuf_record_event(word_t type, word_t tpid, const char *str, ...)
|
|||
if (arg == TRACEBUFFER_MAGIC)
|
||||
break;
|
||||
|
||||
TBUF_STORE_DATA(addr, i, arg);
|
||||
tbuf->store_data(i, arg);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -262,7 +262,7 @@ void intctrl_t::init_arch()
|
|||
total_cpus, cpu_t::count);
|
||||
#ifndef CONFIG_SMP
|
||||
/* make sure the boot CPU is the first */
|
||||
cpu_t::get(0)->id = local_apic.id();
|
||||
cpu_t::get(0)->set_id(local_apic.id());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue