From 412cf94f598ad37404454f2624db9793d5118a60 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Mon, 27 Mar 2023 17:22:00 +0200 Subject: [PATCH] =?UTF-8?q?Added=20simple=20example=20for=20using=20the=20?= =?UTF-8?q?performance=20counter=20syscalls=20in=20Eal=C3=A1nOS.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- repos/mml/run/hpc_test.run | 80 ++++++++++++++++++ repos/mml/src/app/hpc_test/main.cc | 89 ++++++++++++++++++++ repos/mml/src/app/hpc_test/target.mk | 5 ++ repos/mml/src/app/hpc_test/trace_pfc.cc | 105 ++++++++++++++++++++++++ 4 files changed, 279 insertions(+) create mode 100644 repos/mml/run/hpc_test.run create mode 100644 repos/mml/src/app/hpc_test/main.cc create mode 100644 repos/mml/src/app/hpc_test/target.mk create mode 100644 repos/mml/src/app/hpc_test/trace_pfc.cc diff --git a/repos/mml/run/hpc_test.run b/repos/mml/run/hpc_test.run new file mode 100644 index 0000000000..11e9f26d63 --- /dev/null +++ b/repos/mml/run/hpc_test.run @@ -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 { + + + + + + + + + + + + + + + + + + + + + + + + + + +} + +append config { + + + + + 2022-07-20 14:30 + + + + + + + + + + + + 2022-07-20 14:30 + + + + + + + + +} + +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 \ No newline at end of file diff --git a/repos/mml/src/app/hpc_test/main.cc b/repos/mml/src/app/hpc_test/main.cc new file mode 100644 index 0000000000..c23f10d69e --- /dev/null +++ b/repos/mml/src/app/hpc_test/main.cc @@ -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 +#include + +#include +#include +#include +#include + +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(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(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; +} diff --git a/repos/mml/src/app/hpc_test/target.mk b/repos/mml/src/app/hpc_test/target.mk new file mode 100644 index 0000000000..0d72ae45a4 --- /dev/null +++ b/repos/mml/src/app/hpc_test/target.mk @@ -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 + diff --git a/repos/mml/src/app/hpc_test/trace_pfc.cc b/repos/mml/src/app/hpc_test/trace_pfc.cc new file mode 100644 index 0000000000..15fa27beb0 --- /dev/null +++ b/repos/mml/src/app/hpc_test/trace_pfc.cc @@ -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 + +#include +#include +#include +#include + +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; +} \ No newline at end of file