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
|
TBUF_PERFMON_ENERGY
|
||||||
X86_KEEP_LAST_BRANCHES
|
X86_KEEP_LAST_BRANCHES
|
||||||
|
|
||||||
unless ARCH_X86 suppress dependent TRACEBUFFER
|
|
||||||
when X_EVT_LOGGING suppress TBUF_PERFMON TBUF_PERFMON_ENERGY
|
when X_EVT_LOGGING suppress TBUF_PERFMON TBUF_PERFMON_ENERGY
|
||||||
unless TRACEBUFFER and PERFMON suppress TBUF_PERFMON
|
unless TRACEBUFFER and PERFMON suppress TBUF_PERFMON
|
||||||
unless TBUF_PERFMON and SUBARCH_X32 and CPU_X86_P4 suppress TBUF_PERFMON_ENERGY
|
unless TBUF_PERFMON and SUBARCH_X32 and CPU_X86_P4 suppress TBUF_PERFMON_ENERGY
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
##
|
##
|
||||||
## Copyright (C) 2010, Karlsruhe University
|
## Copyright (C) 2010, Karlsruhe University
|
||||||
##
|
##
|
||||||
## File path: generic/Makeconf
|
## File path: kdb/generic/Makeconf
|
||||||
## Description: Generic linkser script for x86.
|
## Description: Generic linkser script for x86.
|
||||||
##
|
##
|
||||||
## Redistribution and use in source and binary forms, with or without
|
## 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/memdump.cc \
|
||||||
kdb/generic/print.cc \
|
kdb/generic/print.cc \
|
||||||
kdb/generic/tid_format.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")
|
ifeq ("$(CONFIG_X86_IO_FLEXPAGES)","y")
|
||||||
SOURCES+= kdb/generic/vrt.cc
|
SOURCES+= kdb/generic/vrt.cc
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2002-2003, 2007-2010, Karlsruhe University
|
* 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
|
* Description: Tracebuffer for PC99 platform
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -27,6 +27,8 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
|
|
||||||
|
#if defined(CONFIG_TRACEBUFFER)
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include <linear_ptab.h>
|
#include <linear_ptab.h>
|
||||||
#include <generic/lib.h>
|
#include <generic/lib.h>
|
||||||
|
@ -36,9 +38,7 @@
|
||||||
#include <kdb/tracebuffer.h>
|
#include <kdb/tracebuffer.h>
|
||||||
#include INC_API(thread.h)
|
#include INC_API(thread.h)
|
||||||
#include INC_API(tcb.h)
|
#include INC_API(tcb.h)
|
||||||
#include INC_GLUE(timer.h)
|
#include INC_GLUE(schedule.h)
|
||||||
|
|
||||||
#if defined(CONFIG_TRACEBUFFER)
|
|
||||||
|
|
||||||
FEATURESTRING ("tracebuffer");
|
FEATURESTRING ("tracebuffer");
|
||||||
|
|
||||||
|
@ -138,8 +138,10 @@ private:
|
||||||
if (tsc == 0) return true;
|
if (tsc == 0) return true;
|
||||||
|
|
||||||
u64_t ttsc = t->tsc;
|
u64_t ttsc = t->tsc;
|
||||||
|
#if defined(CONFIG_TBUF_PERFMON_ENERGY)
|
||||||
if (get_tbuf_config().pmon_e)
|
if (get_tbuf_config().pmon_e)
|
||||||
ttsc <<= X86_PMC_TSC_SHIFT;
|
ttsc <<= X86_PMC_TSC_SHIFT;
|
||||||
|
#endif
|
||||||
return (ttsc >= tsc);
|
return (ttsc >= tsc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -447,9 +449,9 @@ public:
|
||||||
{
|
{
|
||||||
u64_t pmcdelta0;
|
u64_t pmcdelta0;
|
||||||
u64_t pmcdelta1;
|
u64_t pmcdelta1;
|
||||||
|
#if defined(CONFIG_TBUF_PERFMON_ENERGY)
|
||||||
if (get_tbuf_config().pmon_e)
|
if (get_tbuf_config().pmon_e)
|
||||||
{
|
{
|
||||||
|
|
||||||
// Energy mix
|
// Energy mix
|
||||||
c_delta <<= X86_PMC_TSC_SHIFT;
|
c_delta <<= X86_PMC_TSC_SHIFT;
|
||||||
|
|
||||||
|
@ -468,6 +470,7 @@ public:
|
||||||
pmcdelta1 = p_delta / 1000;
|
pmcdelta1 = p_delta / 1000;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
// User and kernel instructions
|
// User and kernel instructions
|
||||||
pmcdelta0 = pmc_delta(rec->pmc0, (word_t) old[cpu].pmc0);
|
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)
|
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;
|
count = size;
|
||||||
tbuf_handler.set_tsc(tsc);
|
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
|
## File path: kdb/glue/v4-x86/Makeconf
|
||||||
## Description:
|
## 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/readmem.cc kdb/glue/v4-x86/resources.cc \
|
||||||
kdb/glue/v4-x86/addrtranslation.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")
|
ifeq ("$(CONFIG_X_CTRLXFER_MSG)","y")
|
||||||
SOURCES+= kdb/glue/v4-x86/ipc.cc
|
SOURCES+= kdb/glue/v4-x86/ipc.cc
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -55,7 +55,6 @@ private:
|
||||||
public:
|
public:
|
||||||
static word_t count;
|
static word_t count;
|
||||||
static cpu_t * get(cpuid_t cpuid) {
|
static cpu_t * get(cpuid_t cpuid) {
|
||||||
ASSERT(cpuid < CONFIG_SMP_MAX_CPUS);
|
|
||||||
return &descriptors[cpuid];
|
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__ */
|
#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
|
* File path: api/v4/smp.cc
|
||||||
* Description: Multiprocessor handling for cross-processor
|
* Description: Multiprocessor handling for cross-processor
|
||||||
|
@ -30,14 +30,16 @@
|
||||||
* $Id: smp.cc,v 1.10 2006/06/16 10:28:44 stoess Exp $
|
* $Id: smp.cc,v 1.10 2006/06/16 10:28:44 stoess Exp $
|
||||||
*
|
*
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
#if defined(CONFIG_SMP)
|
|
||||||
|
|
||||||
#include <sync.h>
|
#include <sync.h>
|
||||||
#include <kdb/tracepoints.h>
|
#include <kdb/tracepoints.h>
|
||||||
#include INC_API(smp.h)
|
#include INC_API(smp.h)
|
||||||
#include INC_API(schedule.h)
|
#include INC_API(schedule.h)
|
||||||
#include INC_API(queueing.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)
|
//#define TRACE_IPI(x...) do { printf("CPU %d: ", get_current_cpu()); printf(x); } while(0)
|
||||||
|
|
||||||
#if defined(CONFIG_SMP_SYNC_REQUEST)
|
#if defined(CONFIG_SMP_SYNC_REQUEST)
|
||||||
|
|
|
@ -790,12 +790,7 @@ INLINE space_t * get_current_space()
|
||||||
return get_current_tcb()->get_space();
|
return get_current_tcb()->get_space();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_SMP
|
#if !defined(CONFIG_SMP)
|
||||||
INLINE cpuid_t get_current_cpu()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
INLINE bool tcb_t::migrate_to_processor(cpuid_t processor)
|
INLINE bool tcb_t::migrate_to_processor(cpuid_t processor)
|
||||||
{
|
{
|
||||||
return processor == 0;
|
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
|
* File path: arch/x86/atomic.h
|
||||||
* Description:
|
* Description:
|
||||||
|
@ -33,7 +33,7 @@ public:
|
||||||
__asm__ __volatile__(X86_LOCK "sub $1, %0" : "=m"(val));
|
__asm__ __volatile__(X86_LOCK "sub $1, %0" : "=m"(val));
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
word_t operator = (word_t val)
|
word_t operator = (word_t val)
|
||||||
{ return this->val = val; }
|
{ return this->val = val; }
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* Copyright (C) 2002-2004, 2006-2008, 2010, Karlsruhe University
|
* Copyright (C) 2002-2004, 2006-2008, 2010, Karlsruhe University
|
||||||
*
|
*
|
||||||
* File path: arch/x86/tracebuffer.h
|
* 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
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
|
@ -31,247 +31,118 @@
|
||||||
#ifndef __ARCH__X86__TRACEBUFFER_H__
|
#ifndef __ARCH__X86__TRACEBUFFER_H__
|
||||||
#define __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)
|
#if defined(CONFIG_TBUF_PERFMON_ENERGY)
|
||||||
#define TRACEBUFFER_SIZE (32 * 1024 * 1024)
|
#define TRACEBUFFER_SIZE (32 * 1024 * 1024)
|
||||||
#else
|
#else
|
||||||
#define TRACEBUFFER_SIZE ( 4 * 1024 * 1024)
|
#define TRACEBUFFER_SIZE ( 4 * 1024 * 1024)
|
||||||
#endif
|
#endif
|
||||||
/**
|
|
||||||
* A tracebuffer record indicates the type of event, the time of the
|
/**********************************************************************
|
||||||
* event, the current thread, a number of event specific parameters,
|
* Sample PMC energy weights
|
||||||
* and potentially the current performance counters.
|
**********************************************************************/
|
||||||
*/
|
#if 0
|
||||||
class tracerecord_t
|
/* 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:
|
tsc = x86_rdtsc();
|
||||||
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;
|
|
||||||
|
|
||||||
};
|
if (config.pmon)
|
||||||
|
|
||||||
|
|
||||||
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
|
|
||||||
{
|
{
|
||||||
ofs_counters = sizeof(word_t) * 8,
|
switch (config.pmon_cpu)
|
||||||
};
|
|
||||||
|
|
||||||
void initialize (void)
|
|
||||||
{
|
{
|
||||||
magic = TRACEBUFFER_MAGIC;
|
case 0:
|
||||||
current = 0;
|
// P2/P3/K8
|
||||||
mask = TBUF_DEFAULT_MASK;
|
pmc0 = x86_rdpmc(0);
|
||||||
sizemask = TRACEBUFFER_SIZE-1;
|
pmc1 = x86_rdpmc(1);
|
||||||
config.raw = 0;
|
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)
|
#if defined(CONFIG_SMP)
|
||||||
config.smp = 1;
|
config.smp = 1;
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_TBUF_PERFMON)
|
#if defined(CONFIG_TBUF_PERFMON)
|
||||||
config.pmon = 1;
|
config.pmon = 1;
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_TBUF_PERFMON_ENERGY)
|
#if defined(CONFIG_TBUF_PERFMON_ENERGY)
|
||||||
config.pmon_e = 1;
|
config.pmon_e = 1;
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_CPU_X86_P4)
|
#if defined(CONFIG_CPU_X86_P4)
|
||||||
config.pmon_cpu = 1;
|
config.pmon_cpu = 1;
|
||||||
#endif
|
#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__ */
|
#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
|
* File path: arch/x86/x64/ptab.h
|
||||||
* Description: X86-64 pagetable management (4KByte long mode)
|
* Description: X86-64 pagetable management (4KByte long mode)
|
||||||
|
@ -52,7 +52,8 @@ class x86_pgent_t
|
||||||
public:
|
public:
|
||||||
enum pagesize_e {
|
enum pagesize_e {
|
||||||
size_4k = 0,
|
size_4k = 0,
|
||||||
size_2m = 1
|
size_2m = 1,
|
||||||
|
size_superpage = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
// predicates
|
// 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
|
* File path: arch/x86/x64/tss.h
|
||||||
* Description: AMD64 Task State Segment
|
* Description: AMD64 Task State Segment
|
||||||
|
|
|
@ -371,6 +371,16 @@ static SECTION(SEC_INIT) void perfmon_init( void )
|
||||||
ppc_set_pmc4( 0 );
|
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 )
|
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");
|
TRACE_INIT("Initializing boot CPU\n");
|
||||||
cpu_init( 0 );
|
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");
|
TRACE_INIT("Initializing kernel debugger\n");
|
||||||
if( get_kip()->kdebug_init )
|
if( get_kip()->kdebug_init )
|
||||||
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);
|
init_swtlb[idx].tlb1.raw, init_swtlb[idx].tlb2.raw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
current_cpu = cpu;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,6 @@ DECLARE_KMEM_GROUP (kmem_utcb);
|
||||||
|
|
||||||
space_t * kernel_space = NULL;
|
space_t * kernel_space = NULL;
|
||||||
addr_t utcb_page = 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)
|
#if defined(CONFIG_SMP)
|
||||||
/* May be that we've already created a bitmap on a different cpu */
|
/* 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;
|
return false;
|
||||||
|
|
||||||
if (get_io_bitmap() != get_io_bitmap(data.reference_ptab))
|
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);
|
get_top_pdir_phys(cpu), cpu);
|
||||||
x86_mmu_t::set_active_pagetable((word_t)get_top_pdir_phys(cpu));
|
x86_mmu_t::set_active_pagetable((word_t)get_top_pdir_phys(cpu));
|
||||||
x86_mmu_t::flush_tlb(true);
|
x86_mmu_t::flush_tlb(true);
|
||||||
|
#if defined(CONFIG_SMP)
|
||||||
current_cpu = cpu;
|
current_cpu = cpu;
|
||||||
|
#endif
|
||||||
TRACE_INIT("\tCPU local pagetable activated %x (CPU %d)\n",
|
TRACE_INIT("\tCPU local pagetable activated %x (CPU %d)\n",
|
||||||
x86_mmu_t::get_active_pagetable(), cpu);
|
x86_mmu_t::get_active_pagetable(), cpu);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -221,20 +221,5 @@ INLINE void tcb_t::release_copy_area (void)
|
||||||
resources.release_copy_area (this, true);
|
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__ */
|
#endif /* !__GLUE__V4_X86__TCB_H__ */
|
||||||
|
|
|
@ -34,9 +34,148 @@
|
||||||
|
|
||||||
|
|
||||||
#if defined(CONFIG_TRACEBUFFER)
|
#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_DEFAULT (1 << 0)
|
||||||
#define TB_USERID_START (100)
|
#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
|
* 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 INC_ARCH(tracebuffer.h)
|
||||||
#include <stdarg.h> /* for va_list, ... comes with gcc */
|
#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...) \
|
#define tbuf_record_event(type, tpid, str, args...) \
|
||||||
__tbuf_record_event(type, tpid, str, ##args, TRACEBUFFER_MAGIC);
|
__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;
|
va_list args;
|
||||||
word_t arg;
|
word_t arg;
|
||||||
|
|
||||||
word_t addr = TBUF_GET_NEXT_RECORD (type, tpid);
|
tracebuffer_t *tbuf = get_tracebuffer();
|
||||||
|
if(!tbuf->next_record(type, tpid))
|
||||||
if (addr == 0)
|
return;
|
||||||
return;
|
|
||||||
|
tbuf->store_string(str);
|
||||||
TBUF_STORE_STR (addr, str);
|
|
||||||
|
|
||||||
va_start(args, 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)
|
if (arg == TRACEBUFFER_MAGIC)
|
||||||
break;
|
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);
|
total_cpus, cpu_t::count);
|
||||||
#ifndef CONFIG_SMP
|
#ifndef CONFIG_SMP
|
||||||
/* make sure the boot CPU is the first */
|
/* 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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue