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

memguard: in-lab tests, fixed bug, all benchmarks look correct

parent e496d4e3
......@@ -28,7 +28,7 @@ uint64_t read_cycle_counter(void)
#define printf xil_printf
#define QEMU 1
#define QEMU 0
#define MASTER_CORE_ID 0U
......@@ -45,11 +45,11 @@ uint64_t read_cycle_counter(void)
#define ICI_INT_PRIORITY 232
#define BENCHMARK_ICI_INT_ID 2
#define SECONDS_OF_BENCHMARKING 2
#define SECONDS_OF_BENCHMARKING 10
#define TIMER_HZ 4
#define TIMES_TO_COUNT (SECONDS_OF_BENCHMARKING * TIMER_HZ)
#define NUMBER_OF_BENCHMARKS 3
#define NUMBER_OF_BENCHMARKS 17
#define ARRAY_TYPE double
#define ARRAY_SIZE 12000000 // 12 Million elements = 96 MB space * 3 arrays = 288 MB total
......@@ -67,6 +67,8 @@ uint64_t bw_used;
/* Used for stopping the while loop when the timer has counted 10 seconds */
static volatile uint32_t not_stop_timer;
static volatile uint32_t start_slave_bench;
/* Used for counting how many fractions of time have occurred already and to stop the timer when it reaches 10 seconds*/
volatile uint32_t ticks;
......@@ -91,7 +93,13 @@ uint64_t memguard_cycle_count;
uint64_t overflow_calls;
/* */
uint64_t suspend_calls;
uint64_t reclaim_tries;
/* */
uint64_t reclaim_exec;
/* */
uint64_t reclaim_val;
/* */
uint64_t suspend_exec;
......@@ -154,8 +162,6 @@ void init_benchmark()
else
benchmark_slave_setup();
benchmark_timer_setu_2();
#if(QEMU == 0)
{
/* PMU counters are already enabled by MemGuard therefore we don't need to enable them again */
......@@ -170,13 +176,22 @@ void init_benchmark()
}
void start_benchmarks() {
uint64_t data[17][10] = {0};
uint64_t data[17][11] = {0};
/* setting the random function, used for getting random indexes in array */
srand(pmu_read_cyclecount());
printf("\n\rstart benchmark\n\r");
if(core_id == MASTER_CORE_ID) {
XScuGic_SoftwareIntr(interrupt_controller, BENCHMARK_ICI_INT_ID, XSCUGIC_SPI_CPU1_MASK);
} else {
start_slave_bench = 0;
while(!start_slave_bench){
}
}
/* Iterating over all benchmarks and measuring each of them for 10s */
for (int i = 0; i < NUMBER_OF_BENCHMARKS; i++) {
......@@ -189,14 +204,14 @@ void start_benchmarks() {
for (int j = 0; j < TIME_FRAMES_IN_ARRAY; j++)
trace_arr[j] = 0;
/* variable used for stoping the loop when the timer has counted 10 seconds */
/* variable used for stopping the loop when the timer has counted 10 seconds */
not_stop_timer = 1;
/* resetting all the variables which keep count of the ocurring events */
/* resetting all the variables which keep count of the occurring events */
ticks = 0;
cycle_count = bus_accesses = instr_exec = 0;
memguard_cycle_count = windows_count = bw_used = 0;
overflow_calls = suspend_calls = suspend_exec = bw_used_before_susp = 0;
cycle_count = bus_accesses = instr_exec = reclaim_val = 0;
memguard_cycle_count = windows_count = bw_used = reclaim_exec = 0;
overflow_calls = reclaim_tries = suspend_exec = bw_used_before_susp = 0;
#if(QEMU == 0)
{
......@@ -209,7 +224,6 @@ void start_benchmarks() {
if (core_id == MASTER_CORE_ID) {
XTtcPs_ResetCounterValue(&benchmark_timer);
XTtcPs_Start(&benchmark_timer);
XTtcPs_Start(&benchmark_timer_2);
while (not_stop_timer) {
(*bench_arr[i])();
......@@ -219,7 +233,6 @@ void start_benchmarks() {
(* bench_arr[16])();
}
}
XTtcPs_Stop(&benchmark_timer_2);
data[i][0] = instr_exec;
data[i][1] = cycle_count;
......@@ -228,11 +241,13 @@ void start_benchmarks() {
data[i][4] = windows_count;
data[i][5] = bw_used;
data[i][6] = overflow_calls;
data[i][7] = suspend_calls;
data[i][7] = reclaim_tries;
data[i][8] = suspend_exec;
data[i][9] = reclaim_exec;
data[i][10] = reclaim_val;
}
/* trick used for delaying the print the core 1*/
/* trick used for delaying the printf of the core 1*/
if(core_id != MASTER_CORE_ID){
int val = 0;
for (int j = 0; j < 50000000; j++)
......@@ -245,10 +260,12 @@ void start_benchmarks() {
bus_accesses = data[i][2];
memguard_cycle_count = data[i][3];
windows_count = data[i][4];
bw_used = data[i][5];
bw_used = data[i][5] / windows_count;
overflow_calls = data[i][6];
suspend_calls = data[i][7];
reclaim_tries = data[i][7];
suspend_exec = data[i][8];
reclaim_exec = data[i][9];
reclaim_val = data[i][10];
double ipc = (double) instr_exec / (double) cycle_count;
uint32_t ipc_whole = (uint32_t) ipc;
......@@ -260,15 +277,17 @@ void start_benchmarks() {
uint64_t bandwidth = bus_accesses / SECONDS_OF_BENCHMARKING * SIZE_MEM_READ / MB_IN_BYTE;
//printf("\n\rc: %u b: %d bus acc: %llu IPC: %u.%03u B/W %llu MB/s ",
// core_id, (i + 1), bus_accesses, ipc_whole, ipc_decimal, bandwidth);
printf("\n\rc: %u b: %d bus acc: %llu IPC: %u.%03u B/W %llu MB/s ",
core_id, (i + 1), bus_accesses, ipc_whole, ipc_decimal, bandwidth);
printf("cycl: %llu memg_cycl: %llu over: %u.%03u windows: %llu tot_bw %llu inst: %llu ",
cycle_count, memguard_cycle_count, overhead_whole, overhead_decimal,
windows_count, bw_used, instr_exec);
printf("overf: %llu susp_call: %llu susp_exec: %llu bw_before_susp %llu\n\r",
overflow_calls, suspend_calls, suspend_exec, bw_used_before_susp);
reclaim_val /= windows_count;
printf("overf: %llu reclaim_tries: %llu reclaim_exec %llu reclaim_val %llu susp_exec: %llu bw_before_susp %llu\n\r",
overflow_calls, reclaim_tries, reclaim_exec, reclaim_val, suspend_exec, bw_used_before_susp);
}
printf("\n\rIPC:\n\r");
......@@ -304,11 +323,16 @@ void trace_entrance_overflow_handler()
}
void trace_suspend_routine_call()
void trace_reclaim_tries()
{
suspend_calls++;
reclaim_tries++;
}
void trace_reclaim_exec(uint32_t reclaim)
{
reclaim_exec++;
reclaim_val += reclaim;
}
void trace_suspend_routine()
{
uint64_t local = suspend_exec;
......@@ -332,7 +356,7 @@ void stop_benchmark_trace()
bus_accesses += pmu_read_counter(BENCH_1_CNTR_ID_BUS_ACCESS);
pmu_write_counter(BENCH_1_CNTR_ID_BUS_ACCESS, 0);
instructions += pmu_read_counter(BENCH_2_CNTR_ID_INSTR_EX);
instr_exec += pmu_read_counter(BENCH_2_CNTR_ID_INSTR_EX);
pmu_write_counter(BENCH_2_CNTR_ID_INSTR_EX, 0);
}
#endif
......@@ -429,7 +453,7 @@ void benchmark_timer_setu_2()
// The following call will map the frequency to the interval and prescaler values.
XTtcPs_CalcIntervalFromFreq(&benchmark_timer_2, timer_hz, &INTERVAL_BENCH, &PRESCALER_benchmark);
// Set the interval and pre-scale
// Set the interval and prescale
XTtcPs_SetInterval(&benchmark_timer_2, INTERVAL_BENCH);
XTtcPs_SetPrescaler(&benchmark_timer_2, PRESCALER_benchmark);
......@@ -451,6 +475,7 @@ void benchmark_slave_setup()
status = XScuGic_Connect(interrupt_controller, BENCHMARK_ICI_INT_ID,
(Xil_ExceptionHandler)handler_timer_interrupt, (void *)interrupt_controller);
configASSERT(status == XST_SUCCESS);
XScuGic_SetPriorityTriggerType(interrupt_controller, BENCHMARK_ICI_INT_ID, ICI_INT_PRIORITY, 0b01);
......@@ -463,20 +488,28 @@ void benchmark_slave_setup()
*/
void handler_timer_interrupt(void *callback_ref)
{
// read the interrupt status, then write it back to clear the interrupt.
u32 status_event = XTtcPs_GetInterruptStatus((XTtcPs *)callback_ref);
#if(QEMU == 0)
{
int32_t status;
if(core_id == MASTER_CORE_ID)
status = XScuGic_SoftwareIntr(interrupt_controller, BENCHMARK_ICI_INT_ID, XSCUGIC_SPI_CPU1_MASK);
}
#endif
// we clear the interrupt status if it was triggered by a timer
if ((XTTCPS_IXR_INTERVAL_MASK & status_event) != 0)
XTtcPs_ClearInterruptStatus((XTtcPs *)callback_ref, status_event);
#if(QEMU == 0)
if(core_id == MASTER_CORE_ID)
{
int32_t status;
if(core_id == MASTER_CORE_ID)
status = XScuGic_SoftwareIntr(interrupt_controller, BENCHMARK_ICI_INT_ID, XSCUGIC_SPI_CPU1_MASK);
// read the interrupt status, then write it back to clear the interrupt.
u32 status_event = XTtcPs_GetInterruptStatus((XTtcPs *)callback_ref);
// we clear the interrupt status if it was triggered by a timer
if ((XTTCPS_IXR_INTERVAL_MASK & status_event) != 0)
XTtcPs_ClearInterruptStatus((XTtcPs *)callback_ref, status_event);
} else {
if(start_slave_bench == 0){
start_slave_bench = 1;
return;
}
}
#endif
/* We are counting 40 times 0.25 seconds because the counters would overflow in case
of monitoring for more than 0.25 second */
......
......@@ -104,9 +104,6 @@
#define SIZE_MEM_ACCESS_IN_BYTE 16
#define ACCESSES_PER_MB MB_IN_BYTE / SIZE_MEM_ACCESS_IN_BYTE
/* Minimum Guaranteed bandwidth of the main memory in MB/s */
#define MIN_GUARANTEED_BW_IN_MB_PER_S 1200U
/* Minimum Guaranteed bandwidth of the main memory in BUS_ACCESS per ms - 78.000 BUS_ACCESS/ms for 1200 MB/S*/
#define MIN_GUARANTEED_BANDWIDTH (uint32_t) (MIN_GUARANTEED_BW_IN_MB_PER_S * ACCESSES_PER_MB * WINDOW_TIME)
......@@ -123,10 +120,7 @@
#define OCM_ADDRESS 0xFFFC0000
/* Weight used for the ema() function */
#define ALPHA_EMA ((float) 0.1)
/* Proportional Share mode - to be set to 1 for activating it, set to 0 do deactivate it */
#define PROPORTIONAL_SHARE 0
#define ALPHA_EMA ((float) 0.05)
/**
* Structure used to monitor main memory access activity of one task
......@@ -256,7 +250,7 @@ static void assert_print(const char8 *FilenamePtr, s32 LineNumber)
* @param bandwidth in MB/s
* @return in BUS_ACCESS events / window time
*/
inline uint32_t convert_mb_to_events(uint32_t bandwidth)
uint32_t convert_mb_to_events(uint32_t bandwidth)
{
return (uint32_t) (bandwidth * ACCESSES_PER_MB * WINDOW_TIME);
}
......@@ -394,7 +388,7 @@ BaseType_t memguard_is_task_susp_by_memguard(TaskHandle_t xTask)
return task_info->tsk_susp_by_memguard;
}
void memguard_reset_task(TaskHandle_t task_handle)
void memguard_task_reset(TaskHandle_t task_handle)
{
uint32_t new_quota;
......@@ -455,11 +449,15 @@ void memguard_reset_task(TaskHandle_t task_handle)
task_info->curr_used_budget = 0;
task_info->budget_finished = 0;
/* It is important to set the flag to pdFALSE before resuming otherwise vTaskResume will think the user is resuming and
* don't let it happen
*/
task_info->tsk_susp_by_memguard = pdFALSE;
/* If the task was suspended by memguard we */
if(task_info->tsk_susp_by_user == pdFALSE && task_info->tsk_susp_by_memguard == pdTRUE){
if(task_info->tsk_susp_by_user == pdFALSE){
vTaskResume(task_handle);
}
task_info->tsk_susp_by_memguard = pdFALSE;
}
void memguard_switch_in()
......@@ -518,6 +516,9 @@ void memguard_switch_out()
{
task_info->counter_val = pmu_read_counter(MEMGUARD_CNTR_ID);
/* writing 0, in order to be sure that the counter will not overflow in the context switch */
pmu_write_counter(MEMGUARD_CNTR_ID, 0);
#if(MEMGUARD_TRACE == 1)
stop_benchmark_trace();
#endif
......@@ -747,6 +748,7 @@ static void periodic_timer_handler_master(void *callback_ref)
XTtcPs_ClearInterruptStatus((XTtcPs *)callback_ref, status_event);
}
//convert_mb_to_events(100)
/* in the new window the global shared budget has to be reset to 0 */
atomic_store(&(memguard_info.global_budget), 0);
......@@ -787,7 +789,7 @@ static void periodic_timer_handler_slave(void *callback_ref)
u64 attrib = (NORM_NONCACHE | INNER_SHAREABLE | OUTER_SHAREABLE);
Xil_SetTlbAttributes(OCM_ADDRESS, attrib);
Xil_DCacheEnable();
Xil_DCacheEnable();
Xil_SetTlbAttributes(OCM_ADDRESS, attrib);
/* we use cores_ready variable to check if we were the ones suspending the scheduler or was the user.
......@@ -852,15 +854,9 @@ static void reset_window_routine(void *pvParameter1, uint32_t ulParameter2)
*/
void overflow_interrupt_handler(void *callback_ref)
{
// read the interrupt status, then write it back to clear the interrupt.
u32 status_event = XTtcPs_GetInterruptStatus((XTtcPs *)callback_ref);
// we clear the interrupt status if it was triggered by a timer
if ((XTTCPS_IXR_INTERVAL_MASK & status_event) != 0)
XTtcPs_ClearInterruptStatus((XTtcPs *)callback_ref, status_event);
#if (MEMGUARD_TEST)
start_memguard_trace();
trace_entrance_overflow_handler();
#endif
#if (QEMU == 0)
......@@ -874,14 +870,10 @@ void overflow_interrupt_handler(void *callback_ref)
}
#endif
// TODO: need a check here if used budget < curr_ass_budget, means we didn't finish it yet
#if(MEMGUARD_TEST == 1)
trace_entrance_overflow_handler();
#endif
// TODO: IMP!!! need a check here if used budget < curr_ass_budget, means we didn't finish it yet
#if (QEMU == 0)
pmu_clear_interrupts();
pmu_clear_interrupt(MEMGUARD_CNTR_ID);
#endif
TaskHandle_t curr_task = xTaskGetCurrentTaskHandle();
......@@ -896,6 +888,9 @@ void overflow_interrupt_handler(void *callback_ref)
/* If there is still global_budget we can try to take and assign part of it to the task */
if(find_new_quota(task_info) == pdTRUE){
pmu_write_counter(MEMGUARD_CNTR_ID, task_info->counter_val);
#if (MEMGUARD_TEST == 1)
{
stop_memguard_trace();
......@@ -926,7 +921,7 @@ void overflow_interrupt_handler(void *callback_ref)
/* incrementing the budget_used_in_window with the budget used by the current task */
atomic_fetch_add(&(memguard_info.budget_used_in_window), task_info->curr_used_budget);
atomic_uint sum_of_quota_used = atomic_load(&(memguard_info.budget_used_in_window));
#if( PROPORTIONAL_SHARE == 1)
{
/* if total quota already used exceeds the minimum guaranteed bandwidth then a new time window has to be started */
......@@ -948,10 +943,6 @@ void overflow_interrupt_handler(void *callback_ref)
}
#endif
#if(MEMGUARD_TEST == 1)
trace_suspend_routine_call();
#endif
/* suspend the task because it has used all its quota */
xTimerPendFunctionCallFromISR(suspend_task_routine, curr_task, 0, NULL);
portYIELD_FROM_ISR(pdTRUE);
......@@ -985,15 +976,26 @@ BaseType_t find_new_quota(memguard_task_info* task_info)
return pdFALSE;
} else {
#if(MEMGUARD_TEST == 1)
trace_reclaim_tries();
#endif
reclaimed = min(global_budget_read, reclaimed);
atomic_store(&new_global_budget, (global_budget_read - reclaimed));
if(atomic_compare_exchange_strong(&(memguard_info.global_budget), &(global_budget_read), new_global_budget)){
task_info->counter_val = mask_value(reclaimed);
task_info->cur_ass_budget = reclaimed;
return pdTRUE;
#if (MEMGUARD_TEST)
{
trace_reclaim_exec(reclaimed);
}
#endif
return pdTRUE;
} else {
// TODO: check if happens
// TODO: PROIFILE check if happens
}
}
}
......@@ -1032,8 +1034,14 @@ void suspend_task_routine(void *pvParameter1, uint32_t ulParameter2)
#endif
}
/**
*
*/
void memguard_vTaskSuspend(TaskHandle_t task_handle, memguard_task_info *task_info)
{
if(task_handle == memguard_task_handle)
return;
/* taking notice that memguard suspended the task in order to not let other tasks
to resume it before the new window starts */
task_info->tsk_susp_by_memguard = pdTRUE;
......
......@@ -85,7 +85,8 @@ void pmu_init_counters()
{
enable_user_access_to_counters();
set_pmcr_el0();
pmu_clear_interrupts();
// TODO: improve
pmu_clear_interrupt(MEMGUARD_CNTR_ID);
}
void pmu_enable_counter_for_event(uint32_t idx, uint32_t event_type)
......@@ -128,9 +129,9 @@ void pmu_disable_intr(uint32_t idx)
isb();
}
void pmu_clear_interrupts()
void pmu_clear_interrupt(uint32_t idx)
{
write_register(PMOVSCLR_EL0, 1);
write_register(PMOVSCLR_EL0, (1 << idx));
}
void pmu_start_counter(uint32_t count_val)
......
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