/*
 * 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>

static u8_t max_partitions;

static void ensure_w_xor_x(k_mem_partition_attr_t attrs)
{
#if defined(CONFIG_EXECUTE_XOR_WRITE) && __ASSERT_ON
	bool writable = K_MEM_PARTITION_IS_WRITABLE(attrs);
	bool executable = K_MEM_PARTITION_IS_EXECUTABLE(attrs);

	__ASSERT(writable != executable, "writable page not executable");
#else
	ARG_UNUSED(attrs);
#endif
}

void k_mem_domain_init(struct k_mem_domain *domain, u32_t num_parts,
		struct k_mem_partition *parts[])
{
	unsigned int key;

	__ASSERT(domain != NULL, "");
	__ASSERT(num_parts == 0 || parts != NULL, "");
	__ASSERT(num_parts <= max_partitions, "");

	key = irq_lock();

	domain->num_partitions = num_parts;
	memset(domain->partitions, 0, sizeof(domain->partitions));

	if (num_parts) {
		u32_t i;

		for (i = 0; i < num_parts; i++) {
			__ASSERT(parts[i], "");

			ensure_w_xor_x(parts[i]->attr);

			domain->partitions[i] = *parts[i];
		}
	}

	sys_dlist_init(&domain->mem_domain_q);

	irq_unlock(key);
}

void k_mem_domain_destroy(struct k_mem_domain *domain)
{
	unsigned int key;
	sys_dnode_t *node, *next_node;

	__ASSERT(domain != NULL, "");

	key = irq_lock();

	/* Handle architecture specifc 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;
	}

	irq_unlock(key);
}

void k_mem_domain_add_partition(struct k_mem_domain *domain,
			       struct k_mem_partition *part)
{
	int p_idx;
	unsigned int key;

	__ASSERT(domain != NULL, "");
	__ASSERT(part != NULL, "");
	__ASSERT((part->start + part->size) > part->start, "");

	ensure_w_xor_x(part->attr);

	key = irq_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++;

	irq_unlock(key);
}

void k_mem_domain_remove_partition(struct k_mem_domain *domain,
				  struct k_mem_partition *part)
{
	int p_idx;
	unsigned int key;

	__ASSERT(domain != NULL, "");
	__ASSERT(part != NULL, "");

	key = irq_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 specifc remove only if it is the current thread*/
	if (_current->mem_domain_info.mem_domain == domain) {
		_arch_mem_domain_partition_remove(domain, p_idx);
	}

	domain->partitions[p_idx].start = 0;
	domain->partitions[p_idx].size = 0;
	domain->partitions[p_idx].attr = 0;

	domain->num_partitions--;

	irq_unlock(key);
}

void k_mem_domain_add_thread(struct k_mem_domain *domain, k_tid_t thread)
{
	unsigned int key;

	__ASSERT(domain != NULL, "");
	__ASSERT(thread != NULL, "");
	__ASSERT(thread->mem_domain_info.mem_domain == NULL,
		 "mem domain unset");

	key = irq_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);
	}

	irq_unlock(key);
}

void k_mem_domain_remove_thread(k_tid_t thread)
{
	unsigned int key;

	__ASSERT(thread != NULL, "");
	__ASSERT(thread->mem_domain_info.mem_domain != NULL, "mem domain set");

	key = irq_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;

	irq_unlock(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);
