mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 17:52:52 +00:00
hw: enable performance counter on ARMv6 and ARMv7
To actually enable the performance counter 'perf_counter' has to be added to the SPECS make variable. Fixes #893.
This commit is contained in:
parent
341290a266
commit
afdabe9df8
31
base-hw/include/kernel/perf_counter.h
Normal file
31
base-hw/include/kernel/perf_counter.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* \brief Performance counter specific functions
|
||||
* \author Josef Soentgen
|
||||
* \date 2013-09-26
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _PERF_COUNTER_H_
|
||||
#define _PERF_COUNTER_H_
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class Perf_counter
|
||||
{
|
||||
public:
|
||||
|
||||
void enable();
|
||||
};
|
||||
|
||||
|
||||
extern Perf_counter *perf_counter();
|
||||
|
||||
}
|
||||
|
||||
#endif /* _PERF_COUNTER_H_ */
|
3
base-hw/lib/mk/arm_v6/enable_perf_counter.mk
Normal file
3
base-hw/lib/mk/arm_v6/enable_perf_counter.mk
Normal file
@ -0,0 +1,3 @@
|
||||
SRC_CC = perf_counter.cc
|
||||
|
||||
vpath %.cc $(REP_DIR)/src/core/arm_v6
|
3
base-hw/lib/mk/arm_v7/enable_perf_counter.mk
Normal file
3
base-hw/lib/mk/arm_v7/enable_perf_counter.mk
Normal file
@ -0,0 +1,3 @@
|
||||
SRC_CC = perf_counter.cc
|
||||
|
||||
vpath %.cc $(REP_DIR)/src/core/arm_v7
|
3
base-hw/lib/mk/perf_counter.mk
Normal file
3
base-hw/lib/mk/perf_counter.mk
Normal file
@ -0,0 +1,3 @@
|
||||
SRC_CC = perf_counter.cc
|
||||
|
||||
vpath %.cc $(REP_DIR)/src/core/
|
1
base-hw/lib/mk/perf_counter/perf_counter.mk
Normal file
1
base-hw/lib/mk/perf_counter/perf_counter.mk
Normal file
@ -0,0 +1 @@
|
||||
LIBS += enable_perf_counter
|
125
base-hw/src/core/arm_v6/perf_counter.cc
Normal file
125
base-hw/src/core/arm_v6/perf_counter.cc
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* \brief Performance counter for ARMv6
|
||||
* \author Josef Soentgen
|
||||
* \date 2013-09-26
|
||||
*
|
||||
* The naming is based on ARM1176JZF-S Technical Reference Manual.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/register.h>
|
||||
|
||||
/* base-hw includes */
|
||||
#include <kernel/perf_counter.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
/**
|
||||
* Performance Monitor Control Register
|
||||
*/
|
||||
struct Pmcr : Register<32>
|
||||
{
|
||||
struct E : Bitfield<0,1> { }; /* enable all counter */
|
||||
struct P : Bitfield<1,1> { }; /* count register reset */
|
||||
struct C : Bitfield<2,1> { }; /* cycle counter reset */
|
||||
struct D : Bitfield<3,1> { }; /* cycle counter divider */
|
||||
|
||||
static access_t enable_and_reset()
|
||||
{
|
||||
return E::bits(1) |
|
||||
P::bits(1) |
|
||||
C::bits(1);
|
||||
}
|
||||
|
||||
static access_t read()
|
||||
{
|
||||
access_t v;
|
||||
asm volatile("mrc p15, 0, %[v], c15, c12, 0" : [v]"=r"(v) :: );
|
||||
return v;
|
||||
}
|
||||
|
||||
static void write(access_t const v)
|
||||
{
|
||||
asm volatile("mcr p15, 0, %[v], c15, c12, 0" :: [v]"r"(v) : );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* System Validation Counter Register
|
||||
*/
|
||||
struct Sysvalcntrr : Register<32>
|
||||
{
|
||||
struct Resetcntr : Bitfield<0,1> { }; /* reset all counter */
|
||||
|
||||
static access_t reset_counter()
|
||||
{
|
||||
return Resetcntr::bits(0);
|
||||
}
|
||||
|
||||
static access_t read()
|
||||
{
|
||||
access_t v;
|
||||
asm volatile("mrc p15, 0, %[v], c15, c12, 1" : [v]"=r"(v) :: );
|
||||
return v;
|
||||
}
|
||||
|
||||
static void write(access_t const v)
|
||||
{
|
||||
asm volatile("mcr p15, 0, %[v], c15, c12, 1" :: [v]"r"(v) : );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Secure User and Non-secure Access Validation Control Register
|
||||
*/
|
||||
struct Accvalctlr : Register<32>
|
||||
{
|
||||
struct V : Bitfield<0,1> { }; /* enable access in user-mode */
|
||||
|
||||
static access_t enable_user_access()
|
||||
{
|
||||
return V::bits(1);
|
||||
}
|
||||
|
||||
static access_t read()
|
||||
{
|
||||
access_t v;
|
||||
asm volatile("mrc p15, 0, %[v], c15, c9, 0" : [v]"=r"(v) :: );
|
||||
return v;
|
||||
}
|
||||
|
||||
static void write(access_t const v)
|
||||
{
|
||||
asm volatile("mcr p15, 0, %[v], c15, c9, 0" :: [v]"r"(v) : );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void Kernel::Perf_counter::enable()
|
||||
{
|
||||
/* enable counters and disable overflow interrupt. */
|
||||
Pmcr::access_t v = Pmcr::enable_and_reset() |
|
||||
Pmcr::D::bits(1); /* count every 64 cycles */
|
||||
Pmcr::write(v);
|
||||
|
||||
Sysvalcntrr::write(Sysvalcntrr::reset_counter());
|
||||
|
||||
/* enable user-mode access */
|
||||
Accvalctlr::write(Accvalctlr::enable_user_access());
|
||||
}
|
||||
|
||||
|
||||
Kernel::Perf_counter* Kernel::perf_counter()
|
||||
{
|
||||
static Kernel::Perf_counter inst;
|
||||
return &inst;
|
||||
}
|
192
base-hw/src/core/arm_v7/perf_counter.cc
Normal file
192
base-hw/src/core/arm_v7/perf_counter.cc
Normal file
@ -0,0 +1,192 @@
|
||||
/*
|
||||
* \brief Performance counter ARMv7
|
||||
* \author Josef Soentgen
|
||||
* \date 2013-09-26
|
||||
*
|
||||
* The naming is based on ARM Architecture Reference Manual ARMv7-A.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/register.h>
|
||||
|
||||
/* base-hw includes */
|
||||
#include <kernel/perf_counter.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
/**
|
||||
* Performance Monitor Control Register
|
||||
*/
|
||||
struct Pmcr : Register<32>
|
||||
{
|
||||
struct E : Bitfield<0,1> { }; /* enable all counters */
|
||||
struct P : Bitfield<1,1> { }; /* performance counter reset */
|
||||
struct C : Bitfield<2,1> { }; /* cycle counter reset */
|
||||
struct D : Bitfield<3,1> { }; /* clock divider */
|
||||
|
||||
static access_t enable_and_reset()
|
||||
{
|
||||
return E::bits(1) |
|
||||
P::bits(1) |
|
||||
C::bits(1);
|
||||
}
|
||||
|
||||
static access_t read()
|
||||
{
|
||||
access_t v;
|
||||
asm volatile("mrc p15, 0, %[v], c9, c12, 0" : [v]"=r"(v) :: );
|
||||
return v;
|
||||
}
|
||||
|
||||
static void write(access_t const v)
|
||||
{
|
||||
asm volatile("mcr p15, 0, %[v], c9, c12, 0" :: [v]"r"(v) : );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Interrupt Enable Clear Register
|
||||
*/
|
||||
struct Pmintenclr : Register<32>
|
||||
{
|
||||
struct C : Bitfield<31,1> { }; /* disable cycle counter overflow interrupt request */
|
||||
struct P0 : Bitfield<0,1> { }; /* disable pmc0 overflow interrupt request */
|
||||
struct P1 : Bitfield<1,1> { }; /* disable pmc1 overflow interrupt reuqest */
|
||||
|
||||
static access_t disable_overflow_intr()
|
||||
{
|
||||
return C::bits(1) |
|
||||
P0::bits(1) |
|
||||
P1::bits(1);
|
||||
}
|
||||
|
||||
static access_t read()
|
||||
{
|
||||
access_t v;
|
||||
asm volatile("mrc p15, 0, %[v], c9, c14, 2" : [v]"=r"(v) :: );
|
||||
return v;
|
||||
}
|
||||
|
||||
static void write(access_t const v)
|
||||
{
|
||||
asm volatile("mcr p15, 0, %[v], c9, c14, 2" :: [v]"r"(v) : );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Count Enable Set Register
|
||||
*/
|
||||
struct Pmcntenset : Register<32>
|
||||
{
|
||||
struct C : Bitfield<31,1> { }; /* cycle counter enable */
|
||||
struct P0 : Bitfield<0,1> { }; /* counter 0 enable */
|
||||
struct P1 : Bitfield<1,1> { }; /* counter 1 enable */
|
||||
struct P2 : Bitfield<2,1> { }; /* counter 2 enable */
|
||||
struct P3 : Bitfield<3,1> { }; /* counter 3 enable */
|
||||
|
||||
static access_t enable_counter()
|
||||
{
|
||||
return C::bits(1) |
|
||||
P0::bits(1) |
|
||||
P1::bits(1) |
|
||||
P2::bits(1) |
|
||||
P3::bits(1);
|
||||
}
|
||||
|
||||
static access_t read()
|
||||
{
|
||||
access_t v;
|
||||
asm volatile("mrc p15, 0, %[v], c9, c12, 1" : [v]"=r"(v) :: );
|
||||
return v;
|
||||
}
|
||||
|
||||
static void write(access_t const v)
|
||||
{
|
||||
asm volatile("mcr p15, 0, %0, c9, c12, 1" :: [v]"r"(v) : );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Overflow Flag Status Register
|
||||
*/
|
||||
struct Pmovsr : Register<32>
|
||||
{
|
||||
struct C : Bitfield<31,1> { }; /* cycle counter overflow flag */
|
||||
struct P0 : Bitfield<0,1> { }; /* counter 0 overflow flag */
|
||||
struct P1 : Bitfield<1,1> { }; /* counter 1 overflow flag */
|
||||
|
||||
static access_t clear_overflow_flags()
|
||||
{
|
||||
return C::bits(1) |
|
||||
P0::bits(1) |
|
||||
P1::bits(1);
|
||||
}
|
||||
|
||||
static access_t read()
|
||||
{
|
||||
access_t v;
|
||||
asm volatile("mrc p15, 0, %[v], c9, c12, 3" : [v]"=r"(v) :: );
|
||||
return v;
|
||||
}
|
||||
|
||||
static void write(access_t const v)
|
||||
{
|
||||
asm volatile("mcr p15, 0, %0, c9, c12, 3" :: [v]"r"(v) : );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* User Enable Register
|
||||
*/
|
||||
struct Pmuseren : Register<32>
|
||||
{
|
||||
struct En : Bitfield<0,1> { }; /* enable user mode access */
|
||||
|
||||
static access_t enable()
|
||||
{
|
||||
return En::bits(1);
|
||||
}
|
||||
|
||||
static access_t read()
|
||||
{
|
||||
access_t v;
|
||||
asm volatile("mrc p15, 0, %[v], c9, c14, 0" : [v]"=r"(v) :: );
|
||||
return v;
|
||||
}
|
||||
|
||||
static void write(access_t const v)
|
||||
{
|
||||
asm volatile("mcr p15, 0, %0, c9, c14, 0" :: [v]"r"(v) : );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void Kernel::Perf_counter::enable()
|
||||
{
|
||||
/* program PMU and enable all counters */
|
||||
Pmcr::write(Pmcr::enable_and_reset());
|
||||
Pmcntenset::write(Pmcntenset::enable_counter());
|
||||
Pmovsr::write(Pmovsr::clear_overflow_flags());
|
||||
|
||||
/* enable user-mode access to counters and disable overflow interrupt. */
|
||||
Pmuseren::write(Pmuseren::enable());
|
||||
Pmintenclr::write(Pmintenclr::disable_overflow_intr());
|
||||
}
|
||||
|
||||
|
||||
Kernel::Perf_counter* Kernel::perf_counter()
|
||||
{
|
||||
static Kernel::Perf_counter inst;
|
||||
return &inst;
|
||||
}
|
@ -34,6 +34,7 @@
|
||||
|
||||
/* base-hw includes */
|
||||
#include <singleton.h>
|
||||
#include <kernel/perf_counter.h>
|
||||
|
||||
using namespace Kernel;
|
||||
|
||||
@ -955,6 +956,9 @@ extern "C" void kernel()
|
||||
/* TrustZone initialization code */
|
||||
trustzone_initialization(pic());
|
||||
|
||||
/* enable performance counter */
|
||||
perf_counter()->enable();
|
||||
|
||||
/* switch to core address space */
|
||||
Cpu::init_virt_kernel(core()->tlb()->base(), core_id());
|
||||
|
||||
|
25
base-hw/src/core/perf_counter.cc
Normal file
25
base-hw/src/core/perf_counter.cc
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* \brief Performance counter dummy
|
||||
* \author Josef Soentgen
|
||||
* \date 2013-09-26
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* base-hw includes */
|
||||
#include <kernel/perf_counter.h>
|
||||
|
||||
|
||||
void Kernel::Perf_counter::enable() { }
|
||||
|
||||
|
||||
Kernel::Perf_counter* Kernel::perf_counter()
|
||||
{
|
||||
static Kernel::Perf_counter inst;
|
||||
return &inst;
|
||||
}
|
@ -11,7 +11,7 @@ TARGET = core
|
||||
CC_OPT += -DCORE_MAIN=_main
|
||||
|
||||
# add library dependencies
|
||||
LIBS += base-common
|
||||
LIBS += base-common perf_counter
|
||||
|
||||
# add include paths
|
||||
INC_DIR += $(REP_DIR)/src/core \
|
||||
|
Loading…
x
Reference in New Issue
Block a user