4344e27c26
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>
288 lines
6.9 KiB
C
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);
|