/*
 * 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, "");

#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) {
		_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, "");

#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++;

	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, "");

	/* Handle architecture-specific remove
	 * only if it is the current thread.
	 */
	if (_current->mem_domain_info.mem_domain == domain) {
		_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) {
		_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) {
		_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 = _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);
