mirror of
https://github.com/mmueller41/genode.git
synced 2026-01-21 12:32:56 +01:00
Added simple example for using the performance counter syscalls in EalánOS.
This commit is contained in:
80
repos/mml/run/hpc_test.run
Normal file
80
repos/mml/run/hpc_test.run
Normal file
@@ -0,0 +1,80 @@
|
||||
set build_components {
|
||||
core init timer app/hpc_test
|
||||
}
|
||||
|
||||
source ${genode_dir}/repos/base/run/platform_drv.inc
|
||||
append_platform_drv_build_components
|
||||
|
||||
build $build_components
|
||||
|
||||
create_boot_directory
|
||||
|
||||
set config {
|
||||
<config>
|
||||
<parent-provides>
|
||||
<service name="LOG"/>
|
||||
<service name="PD"/>
|
||||
<service name="CPU"/>
|
||||
<service name="ROM"/>
|
||||
<service name="RAM"/>
|
||||
<service name="IRQ"/>
|
||||
<service name="IO_MEM"/>
|
||||
<service name="IO_PORT"/>
|
||||
<service name="CAP"/>
|
||||
<service name="RM"/>
|
||||
<service name="SIGNAL"/>
|
||||
<service name="TOPO"/>
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
<any-service><parent/><any-child/></any-service>
|
||||
</default-route>
|
||||
<default caps="200"/>
|
||||
<start name="timer">
|
||||
<resource name="RAM" quantum="16M"/>
|
||||
<provides><service name="Timer"/></provides>
|
||||
<route>
|
||||
<any-service><parent/><any-child/></any-service>
|
||||
</route>
|
||||
</start>
|
||||
}
|
||||
|
||||
append config {
|
||||
<start name="hpc_test1">
|
||||
<binary name="hpc_test"/>
|
||||
<resource name="RAM" quantum="64M"/>
|
||||
<config>
|
||||
<vfs> <dir name="dev"> <log/> <inline name="rtc">2022-07-20 14:30</inline> </dir> </vfs>
|
||||
<libc stdout="/dev/log" stderr="/dev/log" rtc="/dev/rtc"/>
|
||||
</config>
|
||||
<route>
|
||||
<service name="Timer"><child name="timer"/></service>
|
||||
<any-service><parent/><any-child/></any-service>
|
||||
</route>
|
||||
</start>
|
||||
<start name="hpc_test2">
|
||||
<binary name="hpc_test"/>
|
||||
<resource name="RAM" quantum="64M"/>
|
||||
<config>
|
||||
<vfs> <dir name="dev"> <log/> <inline name="rtc">2022-07-20 14:30</inline> </dir> </vfs>
|
||||
<libc stdout="/dev/log" stderr="/dev/log" rtc="/dev/rtc"/>
|
||||
</config>
|
||||
<route>
|
||||
<service name="Timer"><child name="timer"/></service>
|
||||
<any-service><parent/><any-child/></any-service>
|
||||
</route>
|
||||
</start>
|
||||
</config>
|
||||
}
|
||||
|
||||
install_config $config
|
||||
|
||||
set boot_modules {
|
||||
core init timer vfs.lib.so ld.lib.so posix.lib.so libc.lib.so libm.lib.so stdcxx.lib.so hpc_test
|
||||
}
|
||||
|
||||
append_platform_drv_boot_modules
|
||||
|
||||
build_boot_image $boot_modules
|
||||
append qemu_args "-nographic "
|
||||
|
||||
run_genode_until forever
|
||||
89
repos/mml/src/app/hpc_test/main.cc
Normal file
89
repos/mml/src/app/hpc_test/main.cc
Normal file
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* @file main.cc
|
||||
* @author Michael Müller (michael.mueller@uos.de)
|
||||
* @brief Some test for programing hardware performance counters in NOVA
|
||||
* @version 0.1
|
||||
* @date 2022-12-14
|
||||
*
|
||||
* @copyright Copyright (c) 2022
|
||||
*
|
||||
*/
|
||||
|
||||
#include <nova/syscall-generic.h>
|
||||
#include <nova/syscalls.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <x86intrin.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
Nova::mword_t event = 0x26;
|
||||
Nova::mword_t mask = 0x00;
|
||||
Nova::mword_t flags = 0x70000;
|
||||
Nova::uint8_t rc;
|
||||
|
||||
if ((rc = Nova::hpc_ctrl(Nova::HPC_SETUP, 0, 1, event, mask, flags)) != Nova::NOVA_OK) {
|
||||
std::cerr << "Failed to setup performance counter 0" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::cout << "Counter 0 setup" << std::endl;
|
||||
event = 0x60;
|
||||
mask = 0xfe;
|
||||
if ((rc = Nova::hpc_ctrl(Nova::HPC_SETUP, 1, 1, event, mask, flags)) != Nova::NOVA_OK)
|
||||
{
|
||||
std::cerr << "Failed to setup performance counter 1, rc = " << static_cast<Nova::uint32_t>(rc) << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
event = 0x62;
|
||||
mask = 0x1;
|
||||
if ((rc = Nova::hpc_ctrl(Nova::HPC_SETUP, 2, 1, event, mask, flags)) != Nova::NOVA_OK)
|
||||
{
|
||||
std::cerr << "Failed to setup performance counter 2, rc = " << static_cast<Nova::uint32_t>(rc) << std::endl;
|
||||
return -1;
|
||||
}
|
||||
if ((rc = Nova::hpc_start(0, 1)) != Nova::NOVA_OK) {
|
||||
std::cerr << "Failed to start counter 0" << std::endl;
|
||||
return -2;
|
||||
}
|
||||
|
||||
if ((rc = Nova::hpc_start(1, 1)) != Nova::NOVA_OK) {
|
||||
std::cerr << "Failed to start counter 0" << std::endl;
|
||||
return -2;
|
||||
}
|
||||
|
||||
if ((rc = Nova::hpc_start(2, 1)) != Nova::NOVA_OK) {
|
||||
std::cerr << "Failed to start counter 0" << std::endl;
|
||||
return -2;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
|
||||
Nova::mword_t count = 0;
|
||||
|
||||
_mm_clflush(&count);
|
||||
if ((rc = Nova::hpc_read(0, 1, count)) != Nova::NOVA_OK)
|
||||
{
|
||||
std::cerr << "Failed to read counter 0" << std::endl;
|
||||
}
|
||||
std::cout << count << " cache line flushes" << std::endl;
|
||||
|
||||
Nova::mword_t latency = 0;
|
||||
if ((rc = Nova::hpc_read(2, 1, latency)) != Nova::NOVA_OK)
|
||||
{
|
||||
std::cerr << "Failed to read counter 1" << std::endl;
|
||||
}
|
||||
Nova::mword_t l2_requests = 0;
|
||||
if ((rc = Nova::hpc_read(1, 1, l2_requests)) != Nova::NOVA_OK)
|
||||
{
|
||||
std::cerr << "Failed to read counter 1" << std::endl;
|
||||
}
|
||||
count = (latency * 4) / l2_requests;
|
||||
std::cout << "L2 latency:" << count << " cycles" << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
5
repos/mml/src/app/hpc_test/target.mk
Normal file
5
repos/mml/src/app/hpc_test/target.mk
Normal file
@@ -0,0 +1,5 @@
|
||||
TARGET = hpc_test
|
||||
SRC_CC = trace_pfc.cc
|
||||
LIBS += base posix libm libc stdcxx
|
||||
CC_OPT += -Wno-error -Wno-permissive -fpermissive -Wno-error=conversion
|
||||
|
||||
105
repos/mml/src/app/hpc_test/trace_pfc.cc
Normal file
105
repos/mml/src/app/hpc_test/trace_pfc.cc
Normal file
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* @file trace_pfc.cc
|
||||
* @author Michael Müller (michael.mueller@uos.de)
|
||||
* @brief Tests for Genode wrappers around Performance counter syscalls in NOVA
|
||||
* @version 0.1
|
||||
* @date 2022-12-15
|
||||
*
|
||||
* @copyright Copyright (c) 2022
|
||||
*
|
||||
*/
|
||||
|
||||
#include <base/trace/perf.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <x86intrin.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
int main(void)
|
||||
{
|
||||
Trace::Performance_counter::Counter ctr_clflush, ctr_l2_latency, ctr_l2_requests, /*ctr_l3_miss,*/ ctr_l2_prefetch;
|
||||
|
||||
try {
|
||||
ctr_clflush = Trace::Performance_counter::alloc_core();
|
||||
ctr_l2_latency = Trace::Performance_counter::alloc_core();
|
||||
ctr_l2_requests = Trace::Performance_counter::alloc_core();
|
||||
ctr_l2_prefetch = Trace::Performance_counter::acquire(Trace::Performance_counter::Type::CORE);
|
||||
// ctr_l3_miss = Trace::Performance_counter::alloc_cbo();
|
||||
}
|
||||
catch (Trace::Pfc_no_avail)
|
||||
{
|
||||
std::cout << "Unable to allocate performance counters." << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::cout << "Performance counter allocation successful." << std::endl;
|
||||
|
||||
try {
|
||||
Trace::Performance_counter::setup(ctr_clflush, 0x26, 0x00, 0x70000);
|
||||
Trace::Performance_counter::setup(ctr_l2_latency, 0x62, 0x01, 0x30000);
|
||||
Trace::Performance_counter::setup(ctr_l2_requests, 0x60, 0xfe, 0x30000);
|
||||
Trace::Performance_counter::setup(ctr_l2_prefetch, 0xc0, 0x00, 0x30000);
|
||||
//Trace::Performance_counter::setup(ctr_l3_miss, 0x6, 0xff, 0x550f000000000000);
|
||||
} catch (Trace::Pfc_access_error &e) {
|
||||
std::cerr << "PFC access failed. rc=" << e.error_code() << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::cout << "Performance counters successfully set up." << std::endl;
|
||||
|
||||
try {
|
||||
Trace::Performance_counter::start(ctr_clflush);
|
||||
Trace::Performance_counter::start(ctr_l2_latency);
|
||||
Trace::Performance_counter::start(ctr_l2_requests);
|
||||
Trace::Performance_counter::start(ctr_l2_prefetch);
|
||||
//Trace::Performance_counter::start(ctr_l3_miss);
|
||||
} catch (Trace::Pfc_access_error &e) {
|
||||
std::cerr << "PFC access failed. rc=" << e.error_code() << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::cout << "Performance counters started." << std::endl;
|
||||
|
||||
for (;;) {
|
||||
Genode::uint64_t clflushes, latency, requests, /*l3_misses,*/ l2_prefetches;
|
||||
clflushes = latency = requests = l2_prefetches = 0;
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::seconds(2));
|
||||
_mm_clflush(&clflushes);
|
||||
_mm_clflush(&clflushes);
|
||||
|
||||
try {
|
||||
clflushes = Trace::Performance_counter::read(ctr_clflush);
|
||||
latency = Trace::Performance_counter::read(ctr_l2_latency);
|
||||
requests = Trace::Performance_counter::read(ctr_l2_requests);
|
||||
l2_prefetches = Trace::Performance_counter::read(ctr_l2_prefetch);
|
||||
//l3_misses = Trace::Performance_counter::read(ctr_l3_miss);
|
||||
} catch (Trace::Pfc_access_error &e) {
|
||||
std::cerr << "PFC access failed. rc=" << e.error_code() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << clflushes << " cache line flushes." << std::endl;
|
||||
//std::cout << "L2 latency: " << (latency * 4) / requests << " cycles." << std::endl;
|
||||
std::cout << l2_prefetches << " L2 prefetch requests." << std::endl;
|
||||
/*
|
||||
try {
|
||||
Trace::Performance_counter::stop(ctr_l2_prefetch);
|
||||
Trace::Performance_counter::reset(ctr_l2_prefetch, 0xdeadbeef);
|
||||
Trace::Performance_counter::start(ctr_l2_prefetch);
|
||||
std::cout << Trace::Performance_counter::read(ctr_l2_prefetch) << " L2 prefetches after context-switch" << std::endl;
|
||||
Trace::Performance_counter::stop(ctr_l2_prefetch);
|
||||
Trace::Performance_counter::reset(ctr_l2_prefetch, l2_prefetches);
|
||||
Trace::Performance_counter::start(ctr_l2_prefetch);
|
||||
} catch (Trace::Pfc_access_error &e) {
|
||||
std::cerr << "PFC access failed. rc=" << e.error_code() << std::endl;
|
||||
}
|
||||
*/
|
||||
// std::cout << l3_misses << " L3 misses" << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user