zephyr/kernel/mem_domain.c
Patrik Flykt 4344e27c26 all: Update reserved function names
Update reserved function names starting with one underscore, replacing
them as follows:
   '_k_' with 'z_'
   '_K_' with 'Z_'
   '_handler_' with 'z_handl_'
   '_Cstart' with 'z_cstart'
   '_Swap' with 'z_swap'

This renaming is done on both global and those static function names
in kernel/include and include/. Other static function names in kernel/
are renamed by removing the leading underscore. Other function names
not starting with any prefix listed above are renamed starting with
a 'z_' or 'Z_' prefix.

Function names starting with two or three leading underscores are not
automatcally renamed since these names will collide with the variants
with two or three leading underscores.

Various generator scripts have also been updated as well as perf,
linker and usb files. These are
   drivers/serial/uart_handlers.c
   include/linker/kobject-text.ld
   kernel/include/syscall_handler.h
   scripts/gen_kobject_list.py
   scripts/gen_syscall_header.py

Signed-off-by: Patrik Flykt <patrik.flykt@intel.com>
2019-03-11 13:48:42 -04:00

288 lines
6.9 KiB
C

/*
* Copyright (c) 2017 Linaro Limited
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <init.h>
#include <kernel.h>
#include <kernel_structs.h>
#include <kernel_internal.h>
#include <misc/__assert.h>
#include <stdbool.h>
#include <spinlock.h>
static struct k_spinlock lock;
static u8_t max_partitions;
#if (defined(CONFIG_EXECUTE_XOR_WRITE) || \
defined(CONFIG_MPU_REQUIRES_NON_OVERLAPPING_REGIONS)) && __ASSERT_ON
static bool sane_partition(const struct k_mem_partition *part,
const struct k_mem_partition *parts,
u32_t num_parts)
{
bool exec, write;
u32_t last;
u32_t i;
last = part->start + part->size - 1;
exec = K_MEM_PARTITION_IS_EXECUTABLE(part->attr);
write = K_MEM_PARTITION_IS_WRITABLE(part->attr);
if (exec && write) {
__ASSERT(false,
"partition is writable and executable <start %x>",
part->start);
return false;
}
for (i = 0U; i < num_parts; i++) {
bool cur_write, cur_exec;
u32_t cur_last;
cur_last = parts[i].start + parts[i].size - 1;
if (last < parts[i].start || cur_last < part->start) {
continue;
}
#if defined(CONFIG_MPU_REQUIRES_NON_OVERLAPPING_REGIONS)
/* Partitions overlap */
__ASSERT(false, "overlapping partitions <%x...%x>, <%x...%x>",
part->start, last,
parts[i].start, cur_last);
return false;
#endif
cur_write = K_MEM_PARTITION_IS_WRITABLE(parts[i].attr);
cur_exec = K_MEM_PARTITION_IS_EXECUTABLE(parts[i].attr);
if ((cur_write && exec) || (cur_exec && write)) {
__ASSERT(false, "overlapping partitions are "
"writable and executable "
"<%x...%x>, <%x...%x>",
part->start, last,
parts[i].start, cur_last);
return false;
}
}
return true;
}
static inline bool sane_partition_domain(const struct k_mem_domain *domain,
const struct k_mem_partition *part)
{
return sane_partition(part, domain->partitions,
domain->num_partitions);
}
#else
#define sane_partition(...) (true)
#define sane_partition_domain(...) (true)
#endif
void k_mem_domain_init(struct k_mem_domain *domain, u8_t num_parts,
struct k_mem_partition *parts[])
{
k_spinlock_key_t key;
__ASSERT(domain != NULL, "");
__ASSERT(num_parts == 0 || parts != NULL, "");
__ASSERT(num_parts <= max_partitions, "");
key = k_spin_lock(&lock);
domain->num_partitions = 0;
(void)memset(domain->partitions, 0, sizeof(domain->partitions));
if (num_parts != 0) {
u32_t i;
for (i = 0U; i < num_parts; i++) {
__ASSERT(parts[i] != NULL, "");
__ASSERT((parts[i]->start + parts[i]->size) >
parts[i]->start,
"invalid partition %p size %d",
parts[i], parts[i]->size);
#if defined(CONFIG_EXECUTE_XOR_WRITE) || \
defined(CONFIG_MPU_REQUIRES_NON_OVERLAPPING_REGIONS)
__ASSERT(sane_partition_domain(domain,
parts[i]),
"");
#endif
domain->partitions[i] = *parts[i];
domain->num_partitions++;
}
}
sys_dlist_init(&domain->mem_domain_q);
k_spin_unlock(&lock, key);
}
void k_mem_domain_destroy(struct k_mem_domain *domain)
{
k_spinlock_key_t key;
sys_dnode_t *node, *next_node;
__ASSERT(domain != NULL, "");
key = k_spin_lock(&lock);
/* Handle architecture-specific destroy
* only if it is the current thread.
*/
if (_current->mem_domain_info.mem_domain == domain) {
z_arch_mem_domain_destroy(domain);
}
SYS_DLIST_FOR_EACH_NODE_SAFE(&domain->mem_domain_q, node, next_node) {
struct k_thread *thread =
CONTAINER_OF(node, struct k_thread, mem_domain_info);
sys_dlist_remove(&thread->mem_domain_info.mem_domain_q_node);
thread->mem_domain_info.mem_domain = NULL;
}
k_spin_unlock(&lock, key);
}
void k_mem_domain_add_partition(struct k_mem_domain *domain,
struct k_mem_partition *part)
{
int p_idx;
k_spinlock_key_t key;
__ASSERT(domain != NULL, "");
__ASSERT(part != NULL, "");
__ASSERT((part->start + part->size) > part->start,
"invalid partition %p size %d", part, part->size);
#if defined(CONFIG_EXECUTE_XOR_WRITE) || \
defined(CONFIG_MPU_REQUIRES_NON_OVERLAPPING_REGIONS)
__ASSERT(sane_partition_domain(domain, part), "");
#endif
key = k_spin_lock(&lock);
for (p_idx = 0; p_idx < max_partitions; p_idx++) {
/* A zero-sized partition denotes it's a free partition */
if (domain->partitions[p_idx].size == 0) {
break;
}
}
/* Assert if there is no free partition */
__ASSERT(p_idx < max_partitions, "");
domain->partitions[p_idx].start = part->start;
domain->partitions[p_idx].size = part->size;
domain->partitions[p_idx].attr = part->attr;
domain->num_partitions++;
/* Handle architecture-specific remove
* only if it is the current thread.
*/
if (_current->mem_domain_info.mem_domain == domain) {
_arch_mem_domain_partition_add(domain, p_idx);
}
k_spin_unlock(&lock, key);
}
void k_mem_domain_remove_partition(struct k_mem_domain *domain,
struct k_mem_partition *part)
{
int p_idx;
k_spinlock_key_t key;
__ASSERT(domain != NULL, "");
__ASSERT(part != NULL, "");
key = k_spin_lock(&lock);
/* find a partition that matches the given start and size */
for (p_idx = 0; p_idx < max_partitions; p_idx++) {
if (domain->partitions[p_idx].start == part->start &&
domain->partitions[p_idx].size == part->size) {
break;
}
}
/* Assert if not found */
__ASSERT(p_idx < max_partitions, "no matching partition found");
/* Handle architecture-specific remove
* only if it is the current thread.
*/
if (_current->mem_domain_info.mem_domain == domain) {
z_arch_mem_domain_partition_remove(domain, p_idx);
}
/* A zero-sized partition denotes it's a free partition */
domain->partitions[p_idx].size = 0;
domain->num_partitions--;
k_spin_unlock(&lock, key);
}
void k_mem_domain_add_thread(struct k_mem_domain *domain, k_tid_t thread)
{
k_spinlock_key_t key;
__ASSERT(domain != NULL, "");
__ASSERT(thread != NULL, "");
__ASSERT(thread->mem_domain_info.mem_domain == NULL,
"mem domain unset");
key = k_spin_lock(&lock);
sys_dlist_append(&domain->mem_domain_q,
&thread->mem_domain_info.mem_domain_q_node);
thread->mem_domain_info.mem_domain = domain;
if (_current == thread) {
z_arch_mem_domain_configure(thread);
}
k_spin_unlock(&lock, key);
}
void k_mem_domain_remove_thread(k_tid_t thread)
{
k_spinlock_key_t key;
__ASSERT(thread != NULL, "");
__ASSERT(thread->mem_domain_info.mem_domain != NULL, "mem domain set");
key = k_spin_lock(&lock);
if (_current == thread) {
z_arch_mem_domain_destroy(thread->mem_domain_info.mem_domain);
}
sys_dlist_remove(&thread->mem_domain_info.mem_domain_q_node);
thread->mem_domain_info.mem_domain = NULL;
k_spin_unlock(&lock, key);
}
static int init_mem_domain_module(struct device *arg)
{
ARG_UNUSED(arg);
max_partitions = z_arch_mem_domain_max_partitions_get();
/*
* max_partitions must be less than or equal to
* CONFIG_MAX_DOMAIN_PARTITIONS, or would encounter array index
* out of bounds error.
*/
__ASSERT(max_partitions <= CONFIG_MAX_DOMAIN_PARTITIONS, "");
return 0;
}
SYS_INIT(init_mem_domain_module, PRE_KERNEL_1,
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);