Added a non-ASM implementation of the tracebuffer for X86 and PPC

kernels. User to follow soon.
This commit is contained in:
Jan Stoess 2010-08-10 18:34:22 +02:00
parent 497dc5e8d3
commit 32b08ecb1c
20 changed files with 356 additions and 524 deletions

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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__ */

View File

@ -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)

View File

@ -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;

View File

@ -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
}

View File

@ -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; }

View File

@ -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__ */

View File

@ -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__ */

View File

@ -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

View File

@ -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__ */

View File

@ -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

View File

@ -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();

View File

@ -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
}

View File

@ -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

View File

@ -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__ */

View File

@ -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);
}

View File

@ -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
}