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

memguard: major changes to improve code structure, comments and dependencies.

parent 7a06a95d
......@@ -9,7 +9,6 @@
*
******************************************************************************/
#include <xil/drivers/xttcps.h>
#include <stdint-gcc.h>
#include <stdatomic.h>
#include "freertos/FreeRTOS.h"
......@@ -19,13 +18,10 @@
#include "memguard/memguard.h"
#include "memguard/perfmon.h"
#include "xil/xil_printf.h"
#include "xil/drivers/xttcps.h"
#include "xil/drivers/xscugic.h"
#include "xil/xil_cache.h"
#include "xil/xil_mmu.h"
#include "platform_info.h"
#include "metal/sys.h"
#include "metal/atomic.h"
#include "openamp/remoteproc.h"
/*******************************************************************************
* Global Definitions and Macros
......@@ -46,8 +42,9 @@
#define SIZE_MEM_ACCESS_IN_BYTE 16
#define ACCESSES_PER_MB MB_IN_BYTE / SIZE_MEM_ACCESS_IN_BYTE
/* Minimum Guaranteed bandwidth for the main memory in BUS_ACCESS per ms,
eg. 78.000 BUS_ACCESS/ms for 1200 MB/S*/
/* Minimum Guaranteed bandwidth for the main memory in BUS_ACCESS per ms, it
is meant as in total available to all cores. eg. 78.000 BUS_ACCESS/ms for 1200
MB/S*/
#define MIN_GUARANTEED_BUDGET (uint32_t) \
(MIN_GUARANTEED_BW_IN_MB_PER_S * ACCESSES_PER_MB * WINDOW_TIME)
......@@ -137,22 +134,22 @@ typedef struct {
then collects the budget shared by each core. During the window, a
task can claim from it in case it finishes its budget. It is G in the
paper */
atomic_uint global_budget;
volatile atomic_uint global_budget;
/* It keeps track of the cores ready to start during the setup. It helps to
synchronize the cores, in order to start working in the same moment. The
last core to be ready will call the periodic_timer_handler_master() */
atomic_uint cores_ready;
volatile atomic_uint cores_ready;
/* It counts the total bandwidth used by the tasks during a certain moment
of a time window. It is incremented with the quota used by a task,
every time this has finished it and it's being stalled */
atomic_uint budget_used_in_window;
volatile atomic_uint budget_used_in_window;
/* It counts the total bandwidth allocated during the setup to the tasks.
It is used to check if the total bandwidth is <= than the
MIN_GUARANTEED_BUDGET */
atomic_uint bw_allocated;
volatile atomic_uint bw_allocated;
} memguard_glob_info_t;
......@@ -162,7 +159,7 @@ memguard_glob_info_t __attribute__((section (".ocm_ram"))) memguard_info;
/* Base address of the On-Chip Memory where we store the variables shared
among the cores */
extern uint32_t __start_ocm_ram;
extern void *__ocm_ram_start;
/* Instance of the GIC Controller, it is set inside the portZynqUltrascale.c */
extern XScuGic xInterruptController;
......@@ -183,16 +180,16 @@ static void memguard_init_task(void *arg);
static int setup_inter_core_interrupts();
static int setup_pmu_overflow_interrupt();
static void start_slave(void);
static void memguard_timer_setup();
static void check_if_cores_are_ready();
static void periodic_timer_handler_master(void *callback_ref);
static void periodic_timer_handler_slave(void *callback_ref);
static void reset_window_routine(void *pvParameter1, uint32_t ulParameter2);
static void memguard_reset_window_routine(void *pvParameter1,
uint32_t ulParameter2);
static void overflow_interrupt_handler(void *callback_ref);
BaseType_t find_new_budget(memguard_task_info_t *task_info);
static void memguard_overflow_interrupt_handler(void *callback_ref);
uint32_t reclaim_budget(memguard_task_info_t *task_info);
static void suspend_task_routine(void *pvParameter1, uint32_t ulParameter2);
static void memguard_vTaskSuspend(TaskHandle_t task_handle,
......@@ -268,11 +265,10 @@ void memguard_init()
Xil_AssertSetCallback(assert_print);
struct metal_init_params metal_param = METAL_INIT_DEFAULTS;
metal_init(&metal_param);
pmu_init_counters();
pmu_enable_counter_for_event(MEMGUARD_CNTR_ID, ARMV8_PMUV3_PERFCTR_BUS_ACCESS);
// pmu_init_counters();
//TODO: TAKE OUT
//pmu_enable_counter_for_event(MEMGUARD_CNTR_ID,
// ARMV8_PMUV3_PERFCTR_BUS_ACCESS);
/* The task activated at the beginning of scheduling to setup the timer and
then deleted */
......@@ -294,7 +290,8 @@ void memguard_setup_task(TaskHandle_t task_handle, uint32_t bandwidth,
/* MemGuard handles the memory of the memguard_task_info_t
structures, allocating the memory and freeing the memory. The
free memory operation is executed when a task is deleted inside the
function memguard_notify_task_deleted() */
function memguard_notify_task_deleted(). The TCB structure holds only
pointer to the memguard structure */
memguard_task_info_t *new_task_info = pvPortMalloc(sizeof(memguard_task_info_t));
/* Converting the bandwidth into the statically assigned budget and
......@@ -317,20 +314,13 @@ void memguard_setup_task(TaskHandle_t task_handle, uint32_t bandwidth,
MEMGUARD_TASK_BUDGET * NUMBER_CORES);
vTaskSetMemguardTaskInfo(task_handle, new_task_info);
new_task_info->tsk_susp_by_user = pdFALSE;
if(task_handle == memguard_task_handle){
new_task_info->tsk_susp_by_memguard = pdFALSE;
vTaskResume(task_handle);
} else {
new_task_info->tsk_susp_by_memguard = pdTRUE;
}
// TODO: do we need this line
new_task_info->tsk_susp_by_user = pdFALSE;
} else if (task_handle == xTaskGetIdleTaskHandle() ||
xTimerGetTimerDaemonTaskHandle()) {
vTaskResume(task_handle);
new_task_info->tsk_susp_by_memguard = pdTRUE;
} else {
} else {
/* If a task different from the TimerTask and the IdleTask has a NULL
pointer as task_info the system will be halted by a configAssert() */
configASSERT(task_handle != NULL);
......@@ -392,14 +382,7 @@ BaseType_t memguard_can_task_resume(TaskHandle_t xTask)
can_task_resume = task_info->tsk_susp_by_memguard;
} else {
if ((xTask == xTaskGetIdleTaskHandle()) ||
(xTask == xTimerGetTimerDaemonTaskHandle())) {
can_task_resume = pdTRUE;
} else {
can_task_resume = pdFALSE;
}
can_task_resume = pdFALSE;
}
#if (INCLUDE_memguard_benchmark)
......@@ -556,6 +539,11 @@ void memguard_task_switch_out()
#endif
}
void *memguard_get_memguard_task_handle()
{
return memguard_task_handle;
}
/**
* The task sets up memguard, doing the remaining operations which can be done
* only inside a Task context. The interrupts and the timer cannot be setup
......@@ -577,7 +565,6 @@ static void memguard_init_task(void *arg)
configASSERT(status == XST_SUCCESS);
if(XScuGic_GetCpuID() == MASTER_CORE_ID){
start_slave();
memguard_timer_setup();
}
......@@ -615,8 +602,11 @@ static int setup_inter_core_interrupts()
}
/* Connecting the periodic_timer_handler_slave() on each core as a handler
in order to make the handler on each core callable by the master
core, when a new window has to be started */
in order to make the handler on each core callable by the master core, when
a new window has to be started. We are executing this interrupt also on the
master core in order to keep the cores synchronized when calling the
memguard window reset and to be sure that the timing of execution is
almost the same. */
status = XScuGic_Connect(int_controller_ptr, MEMGUARD_ICI_INT_ID,
(Xil_ExceptionHandler)periodic_timer_handler_slave,
(void *)int_controller_ptr);
......@@ -650,8 +640,8 @@ static int setup_pmu_overflow_interrupt()
/* Connect the handler to the interrupt controller */
status = XScuGic_Connect(int_controller_ptr, PMU_INT_ID,
(Xil_ExceptionHandler)overflow_interrupt_handler,
(void *)int_controller_ptr);
(Xil_ExceptionHandler) memguard_overflow_interrupt_handler,
(void *) int_controller_ptr);
if (status != XST_SUCCESS) {
xil_printf("Failed to XScuGic_connect");
......@@ -671,26 +661,6 @@ static int setup_pmu_overflow_interrupt()
return XST_SUCCESS;
}
/**
* This function boots the slave cores. It is suppoeds to be called inside a
* Task in order to work properly
*/
static void start_slave(void)
{
struct hil_proc *hil_proc;
struct remote_proc *proc;
int ret;
hil_proc = platform_create_proc(1);
ret = remoteproc_init("rpc", hil_proc, NULL, NULL, NULL, &proc);
configASSERT(!ret && (proc));
/* booting the core 1 */
ret = remoteproc_boot(proc);
configASSERT(ret == RPROC_SUCCESS);
}
/**
* This function checks if all the cores are ready to start the framework,
* meaning they already started their scheduler and reached this point. The
......@@ -836,9 +806,9 @@ static void periodic_timer_handler_slave(void *callback_ref)
if(atomic_load(&(memguard_info.cores_ready)) > 0){
u64 attrib = (NORM_NONCACHE | INNER_SHAREABLE | OUTER_SHAREABLE);
Xil_SetTlbAttributes(__start_ocm_ram, attrib);
Xil_SetTlbAttributes((UINTPTR) __ocm_ram_start, attrib);
Xil_DCacheEnable();
Xil_SetTlbAttributes(__start_ocm_ram, attrib);
Xil_SetTlbAttributes((UINTPTR) __ocm_ram_start, attrib);
/* We use cores_ready variable here in order to don't enable the
cache a second time, therefore decreasing the value of the
......@@ -846,8 +816,8 @@ static void periodic_timer_handler_slave(void *callback_ref)
atomic_fetch_sub(&(memguard_info.cores_ready), 1);
}
xTimerPendFunctionCallFromISR(reset_window_routine, NULL, 0,
&xHigherPriorityTaskWoken);
xTimerPendFunctionCallFromISR(memguard_reset_window_routine, NULL, 0,
&xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
#if (INCLUDE_memguard_benchmark)
......@@ -864,7 +834,8 @@ static void periodic_timer_handler_slave(void *callback_ref)
* @param pvParameter1 not used
* @param ulParameter2 not used
*/
static void reset_window_routine(void *pvParameter1, uint32_t ulParameter2)
static void memguard_reset_window_routine(void *pvParameter1,
uint32_t ulParameter2)
{
#if (INCLUDE_memguard_benchmark)
{
......@@ -900,7 +871,7 @@ static void reset_window_routine(void *pvParameter1, uint32_t ulParameter2)
*
* @param callback_ref not used
*/
static void overflow_interrupt_handler(void *callback_ref)
static void memguard_overflow_interrupt_handler(void *callback_ref)
{
#if (INCLUDE_memguard_benchmark == 1)
start_memguard_trace();
......@@ -920,6 +891,9 @@ static void overflow_interrupt_handler(void *callback_ref)
memguard_task_info_t *task_info = (memguard_task_info_t *)
pvTaskGetMemguardTaskInfo(curr_task);
/* In case an overflow occurs while the TimerTask, IdleTask or MemGuard
are executing we return. We are not monitoring them. No other task
will reach this point if its task_info is NULL. */
if(task_info == NULL)
return;
......@@ -930,9 +904,13 @@ static void overflow_interrupt_handler(void *callback_ref)
/* If there is still global_budget we can try to take a part of it and
assign it to the task */
if(find_new_budget(task_info) == pdTRUE){
uint32_t reclaimed = reclaim_budget(task_info);
if(reclaimed > 0){
task_info->counter_val = mask_value(reclaimed);
task_info->cur_ass_budget = reclaimed;
/* There will be no context switch where the counter would be
written, therefore we have to write it here ah*/
written, therefore we have to write it here */
pmu_write_counter(MEMGUARD_CNTR_ID, task_info->counter_val);
#if (INCLUDE_memguard_benchmark == 1)
......@@ -1006,7 +984,7 @@ static void overflow_interrupt_handler(void *callback_ref)
* @param task_info of the task with budget finished
* @return pdTRUE if new budget was found, otherwise pdFALSE
*/
BaseType_t find_new_budget(memguard_task_info_t *task_info)
uint32_t reclaim_budget(memguard_task_info_t *task_info)
{
uint32_t reclaimed;
atomic_uint new_global_budget;
......@@ -1017,6 +995,7 @@ BaseType_t find_new_budget(memguard_task_info_t *task_info)
equivalent to 25 MB/s */
if(task_info->curr_used_budget < task_info->ass_budget){
reclaimed = task_info->ass_budget - task_info->curr_used_budget;
} else {
reclaimed = MIN_ASSIGNED_BUDGET;
}
......@@ -1025,7 +1004,8 @@ BaseType_t find_new_budget(memguard_task_info_t *task_info)
atomic_uint global_budget_read = atomic_load(&(memguard_info.global_budget));
if(global_budget_read == 0) {
return pdFALSE;
reclaimed = 0;
break;
} else {
#if(INCLUDE_memguard_benchmark)
......@@ -1035,9 +1015,11 @@ BaseType_t find_new_budget(memguard_task_info_t *task_info)
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)){
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;
......@@ -1046,10 +1028,11 @@ BaseType_t find_new_budget(memguard_task_info_t *task_info)
trace_reclaim_exec(reclaimed);
}
#endif
return pdTRUE;
break;
}
}
}
return reclaimed;
}
/**
......@@ -1067,9 +1050,9 @@ static void suspend_task_routine(void *pvParameter1, uint32_t ulParameter2)
trace_bw_before_suspend(pmu_read_counter(MEMGUARD_CNTR_ID));
#endif
taskDISABLE_INTERRUPTS();
TaskHandle_t task_handle = pvParameter1;
memguard_task_info_t *task_info = (memguard_task_info_t *) pvTaskGetMemguardTaskInfo(task_handle);
memguard_task_info_t *task_info = (memguard_task_info_t *)
pvTaskGetMemguardTaskInfo(task_handle);
#if(INCLUDE_memguard_benchmark)
trace_suspend_routine();
......@@ -1077,8 +1060,6 @@ static void suspend_task_routine(void *pvParameter1, uint32_t ulParameter2)
memguard_vTaskSuspend(task_handle, task_info);
taskENABLE_INTERRUPTS();
#if (INCLUDE_memguard_benchmark)
stop_memguard_trace();
#endif
......
//
// Created by dorel on 20.07.18.
//
#include "slave_boot.h"
#include "openamp/remoteproc.h"
#include "platform_info.h"
void metal_init_()
{
struct metal_init_params metal_param = METAL_INIT_DEFAULTS;
metal_init(&metal_param);
}
/**
* This function boots the slave cores. It is suppoeds to be called inside a
* Task in order to work properly
*/
void start_slave(void)
{
struct hil_proc *hil_proc;
struct remote_proc *proc;
int ret;
hil_proc = platform_create_proc(1);
ret = remoteproc_init("rpc", hil_proc, NULL, NULL, NULL, &proc);
configASSERT(!ret && (proc));
/* booting the core 1 */
ret = remoteproc_boot(proc);
configASSERT(ret == RPROC_SUCCESS);
}
\ No newline at end of file
//
// Created by dorel on 20.07.18.
//
#ifndef MEMGUARD_SLAVE_BOOT_H
#define MEMGUARD_SLAVE_BOOT_H
void metal_init_();
void start_slave(void);
#endif //MEMGUARD_SLAVE_BOOT_H
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