blob: 7ea6e9eb8d405c1f539cb17ca6c28c3141e92c9a [file] [log] [blame]
/*
* Copyright 2017, Data61
* Commonwealth Scientific and Industrial Research Organisation (CSIRO)
* ABN 41 687 119 230.
*
* This software may be distributed and modified according to the terms of
* the BSD 2-Clause license. Note that NO WARRANTY is provided.
* See "LICENSE_BSD2.txt" for details.
*
* @TAG(DATA61_BSD)
*/
#pragma once
/**
*
* Builder functions for thread configs
*
*/
#include <autoconf.h>
#include <sel4utils/gen_config.h>
#include <sel4/types.h>
#include <simple/simple.h>
#include <sel4utils/api.h>
/* Threads and processes use this struct as both need scheduling config parameters */
typedef struct sched_params {
/* seL4 priority for the thread to be scheduled with. */
uint8_t priority;
/* seL4 maximum controlled priority for the thread. */
uint8_t mcp;
/* TCB to derive MCP from when setting priority/mcp (in future API) */
seL4_CPtr auth;
/* true if sel4utils should create an sc */
bool create_sc;
/* sel4 sched control cap for creating sc */
seL4_CPtr sched_ctrl;
/* scheduling parameters */
uint64_t period;
uint64_t budget;
seL4_Word extra_refills;
seL4_Word badge;
/* otherwise use this provided sc */
seL4_CPtr sched_context;
/* affinity for this tcb. Must set sched_ctrl if CONFIG_RT */
seL4_Word core;
} sched_params_t;
typedef struct sel4utils_thread_config {
/* fault_endpoint endpoint to set as the threads fault endpoint. Can be seL4_CapNull. */
seL4_CPtr fault_endpoint;
/* root of the cspace to start the thread in */
seL4_CNode cspace;
/* data for cspace access */
seL4_Word cspace_root_data;
/* use a custom stack size? */
bool custom_stack_size;
/* custom stack size in 4k pages for this thread */
seL4_Word stack_size;
/* true if this thread should have no ipc buffer */
bool no_ipc_buffer;
/* scheduling parameters */
sched_params_t sched_params;
/* true if sel4utils should create a reply */
bool create_reply;
/* otherwise provide one */
seL4_CPtr reply;
} sel4utils_thread_config_t;
static inline sched_params_t sched_params_periodic(sched_params_t params, simple_t *simple, seL4_Word core,
uint64_t period_us,
uint64_t budget_us, seL4_Word extra_refills, seL4_Word badge)
{
if (!config_set(CONFIG_KERNEL_MCS)) {
ZF_LOGW("Setting sched params on non-RT kernel will have no effect");
}
params.sched_ctrl = simple_get_sched_ctrl(simple, core);
params.period = period_us;
params.budget = budget_us;
params.extra_refills = extra_refills;
params.badge = badge;
params.create_sc = true;
return params;
}
static inline sched_params_t sched_params_round_robin(sched_params_t params, simple_t *simple, seL4_Word core,
uint64_t timeslice_us)
{
return sched_params_periodic(params, simple, core, timeslice_us, timeslice_us, 0, 0);
}
static inline sched_params_t sched_params_core(sched_params_t params, seL4_Word core)
{
if (!config_set(CONFIG_KERNEL_MCS)) {
ZF_LOGW("Setting core on RT kernel will have no effect - sched ctrl required");
}
params.core = core;
return params;
}
static inline sel4utils_thread_config_t thread_config_create_reply(sel4utils_thread_config_t config)
{
config.create_reply = true;
return config;
}
static inline sel4utils_thread_config_t thread_config_reply(sel4utils_thread_config_t config, seL4_CPtr reply)
{
config.create_reply = false;
config.reply = reply;
return config;
}
static inline sel4utils_thread_config_t thread_config_sched_context(sel4utils_thread_config_t config,
seL4_CPtr sched_context)
{
config.sched_params.create_sc = false;
config.sched_params.sched_context = sched_context;
return config;
}
static inline sel4utils_thread_config_t thread_config_cspace(sel4utils_thread_config_t config, seL4_CPtr cspace_root,
seL4_Word cspace_root_data)
{
config.cspace = cspace_root;
config.cspace_root_data = cspace_root_data;
return config;
}
static inline sel4utils_thread_config_t thread_config_auth(sel4utils_thread_config_t config, seL4_CPtr tcb)
{
config.sched_params.auth = tcb;
return config;
}
static inline sel4utils_thread_config_t thread_config_new(simple_t *simple)
{
sel4utils_thread_config_t config = {0};
seL4_Word data = api_make_guard_skip_word(seL4_WordBits - simple_get_cnode_size_bits(simple));
config = thread_config_auth(config, simple_get_tcb(simple));
return thread_config_cspace(config, simple_get_cnode(simple), data);
}
static inline sel4utils_thread_config_t thread_config_priority(sel4utils_thread_config_t config, uint8_t priority)
{
config.sched_params.priority = priority;
return config;
}
static inline sel4utils_thread_config_t thread_config_mcp(sel4utils_thread_config_t config, uint8_t mcp)
{
config.sched_params.mcp = mcp;
return config;
}
static inline sel4utils_thread_config_t thread_config_stack_size(sel4utils_thread_config_t config, seL4_Word size)
{
config.stack_size = size;
config.custom_stack_size = true;
return config;
}
static inline sel4utils_thread_config_t thread_config_no_ipc_buffer(sel4utils_thread_config_t config)
{
config.no_ipc_buffer = true;
return config;
}
static inline sel4utils_thread_config_t thread_config_fault_endpoint(sel4utils_thread_config_t config,
seL4_CPtr fault_ep)
{
config.fault_endpoint = fault_ep;
return config;
}
static inline sel4utils_thread_config_t thread_config_default(simple_t *simple, seL4_CPtr cnode, seL4_Word data,
seL4_CPtr fault_ep, uint8_t prio)
{
sel4utils_thread_config_t config = thread_config_new(simple);
config = thread_config_cspace(config, cnode, data);
config = thread_config_fault_endpoint(config, fault_ep);
config = thread_config_priority(config, prio);
if (config_set(CONFIG_KERNEL_MCS)) {
uint64_t timeslice = CONFIG_BOOT_THREAD_TIME_SLICE;
config.sched_params = sched_params_round_robin(config.sched_params, simple, 0, timeslice * US_IN_MS);
}
config = thread_config_create_reply(config);
return config;
}