Commit 2d8bed54 authored by Dorel Coman's avatar Dorel Coman Committed by Oliver Horst
Browse files

memguard: restructured code for the perfon API

parent 0fea0527
/*
* Created by Dorel Coman on 21.10.17.
*
* Functions written in this file are freely inspired by the ARM64 implementation for Linux
* https://elixir.bootlin.com/linux/v4.0/source/arch/arm64/kernel/perf_event.c
*/
#include "memguard/perfmon.h"
......@@ -15,7 +14,7 @@
/* Mask used for extracting the CPU_ID from the MPIDR_EL1 register */
#define CPU_ID_MASK (uint32_t) (0xFF)
/* Macros used for accessing the PMU registers and for their setup */
/* Macros used for accessing and setting up the PMU registers */
#define PMCR_MASK 0x3f
#define PMCR_E (1 << 0) /* Enable all counters */
#define PMCR_P (1 << 1) /* Reset all counters */
......@@ -29,9 +28,9 @@
#define PMUSERENR_ER (1 << 3) /* Event counter read enable */
#define PMUSERENR_ENABLE_ALL 0xD
/**
/*********************************************************
* Registers of the Performance Monitor Unit (PMU)
*/
*********************************************************/
/* Performance Monitors Event Counter Selection Register */
#define PMSELR_EL0 "PMSELR_EL0"
......@@ -71,11 +70,11 @@
void set_pmcr_el0();
void enable_user_access_to_counters();
void pmu_enable_counter(unsigned int idx);
void pmu_type_select(unsigned int idx, unsigned int type);
void pmu_enable_counter(uint32_t idx);
void pmu_type_select(uint32_t idx, uint32_t type);
uint32_t pmu_control_read(void);
void pmu_control_write(u32 val);
void pmu_counter_select(unsigned int idx);
void pmu_counter_select(uint32_t idx);
/***********************************************************************************
* Function definitions
......@@ -85,8 +84,11 @@ void pmu_init_counters()
{
enable_user_access_to_counters();
set_pmcr_el0();
// TODO: improve
pmu_clear_interrupt(MEMGUARD_CNTR_ID);
uint32_t number_of_counters = pmu_get_number_counters();
for (uint32_t i = 0; i < number_of_counters; ++i) {
pmu_clear_interrupt(i);
}
}
void pmu_enable_counter_for_event(uint32_t idx, uint32_t event_type)
......@@ -104,12 +106,12 @@ uint32_t pmu_get_core_id()
return value;
}
uint32_t pmu_counter_has_overflowed()
uint32_t pmu_counter_has_overflowed(uint32_t idx)
{
uint32_t value;
read_register(PMOVSSET_EL0, value);
return value;
return ((value) & (1 << idx));
}
void pmu_enable_intr(uint32_t idx)
......@@ -134,7 +136,7 @@ void pmu_clear_interrupt(uint32_t idx)
write_register(PMOVSCLR_EL0, (1 << idx));
}
void pmu_start_counter(uint32_t count_val)
void pmu_start_counter(uint32_t idx, uint32_t count_val)
{
/* writing the value on the selected counter */
pmu_write_counter(MEMGUARD_CNTR_ID, count_val);
......@@ -165,7 +167,7 @@ uint32_t pmu_read_counter(uint32_t idx)
return value;
}
void pmu_write_counter(u32 idx, u32 value)
void pmu_write_counter(uint32_t idx, uint32_t value)
{
if (idx == 31) {
write_register(PMCCNTR_EL0, value);
......@@ -185,14 +187,14 @@ uint64_t pmu_read_cyclecount(void)
uint32_t pmu_get_number_counters(void)
{
uint32_t count = pmu_control_read();
/* N, bits[15:11] */
/* extracting the bits[15:11] */
count = ((count >> PMCR_N_SHIFT) & PMCR_N_MASK);
return count;
}
/**
* Enable user-mode access to counters. It is fundamental to can use the counters
* in FreeRTOS
* It enables user-mode access to counters. It is important in order to be able
* to use the counters in FreeRTOS
*/
void enable_user_access_to_counters()
{
......@@ -203,7 +205,8 @@ void enable_user_access_to_counters()
}
/**
* pmu_enable_count - enable counter number n (idx)
* This function enables the selected counter in order to make it count. If the counter is not
* enabled, it will not count the occurencies of its selected event type
* @idx: The counter n index
*/
void pmu_enable_counter(uint32_t idx)
......@@ -212,7 +215,8 @@ void pmu_enable_counter(uint32_t idx)
}
/**
*
* This function reads the PMCR_EL0 register and writes it back with the value
* needed in order to activate the PMU counters. The PMCR_E mask enables all the counters
*/
void set_pmcr_el0()
{
......@@ -221,7 +225,8 @@ void set_pmcr_el0()
}
/**
* provides details of the Performance Monitors implementation
* This function returns the value of the PMCR_EL0 register
* @return PMCR_EL0 value
*/
uint32_t pmu_control_read(void)
{
......@@ -231,8 +236,8 @@ uint32_t pmu_control_read(void)
}
/**
* This function writes the PMCR register
* @param val
* This function writes the PMCR register of the PMU
* @param val to be written inside the PMCR register
*/
void pmu_control_write(uint32_t val)
{
......@@ -242,8 +247,8 @@ void pmu_control_write(uint32_t val)
}
/**
* This function selects the counter on which we want to execute some tasks
* @param idx
* This function selects the counter on which it is wanted to executed some PMU operations
* @param idx of the counter to be selecte
*/
void pmu_counter_select(uint32_t idx)
{
......@@ -252,11 +257,11 @@ void pmu_counter_select(uint32_t idx)
}
/**
* This function selects for a define counter, the type of event to be monitored and
* This function selects for the selected counter the type of event to be monitored and
* counted
* @param idx of the counter to be defined
* @param type of the event to be monitored. The events that can be monitored are contained
* in the file events.h
* @param idx of the counter of which it is being selected the event
* @param type of the event to be monitored. Events that can be monitored are contained
* in the file events.h
*/
void pmu_type_select(uint32_t idx, uint32_t type)
{
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment