/*
 * Copyright (c) 2021 Synopsys.
 *
 * SPDX-License-Identifier: Apache-2.0
 */
#ifndef ZEPHYR_ARCH_ARC_CORE_MPU_ARC_MPU_COMMON_INTERNAL_H_
#define ZEPHYR_ARCH_ARC_CORE_MPU_ARC_MPU_COMMON_INTERNAL_H_

#if CONFIG_ARC_MPU_VER == 2 || CONFIG_ARC_MPU_VER == 3
#include "arc_mpu_v2_internal.h"
#elif CONFIG_ARC_MPU_VER == 6
#include "arc_mpu_v6_internal.h"
#else
#error "Unsupported MPU version"
#endif

/**
 * @brief configure the base address and size for an MPU region
 *
 * @param type MPU region type
 * @param base base address in RAM
 * @param size size of the region
 */
static inline int _mpu_configure(uint8_t type, uint32_t base, uint32_t size)
{
	int32_t region_index =  get_region_index_by_type(type);
	uint32_t region_attr = get_region_attr_by_type(type);

	LOG_DBG("Region info: 0x%x 0x%x", base, size);

	if (region_attr == 0U || region_index < 0) {
		return -EINVAL;
	}

	/*
	 * For ARC MPU, MPU regions can be overlapped, smaller
	 * region index has higher priority.
	 */
	_region_init(region_index, base, size, region_attr);

	return 0;
}

/* ARC Core MPU Driver API Implementation for ARC MP */

/**
 * @brief enable the MPU
 */
void arc_core_mpu_enable(void)
{
	/* Enable MPU */
	z_arc_v2_aux_reg_write(_ARC_V2_MPU_EN,
		z_arc_v2_aux_reg_read(_ARC_V2_MPU_EN) | AUX_MPU_EN_ENABLE);
}

/**
 * @brief disable the MPU
 */
void arc_core_mpu_disable(void)
{
    /* Disable MPU */
	z_arc_v2_aux_reg_write(_ARC_V2_MPU_EN,
		z_arc_v2_aux_reg_read(_ARC_V2_MPU_EN) & AUX_MPU_EN_DISABLE);
}

/**
 * @brief configure the thread's MPU regions
 *
 * @param thread the target thread
 */
void arc_core_mpu_configure_thread(struct k_thread *thread)
{
#if defined(CONFIG_USERSPACE)
	/* configure stack region of user thread */
	if (thread->base.user_options & K_USER) {
		LOG_DBG("configure user thread %p's stack", thread);
		if (_mpu_configure(THREAD_STACK_USER_REGION,
					 (uint32_t)thread->stack_info.start,
					 thread->stack_info.size) < 0) {
			LOG_ERR("user thread %p's stack failed", thread);
			return;
		}
	}

	LOG_DBG("configure thread %p's domain", thread);
	arc_core_mpu_configure_mem_domain(thread);
#endif
}


/**
 * @brief configure the default region
 *
 * @param region_attr region attribute of default region
 */
void arc_core_mpu_default(uint32_t region_attr)
{
	uint32_t val =  z_arc_v2_aux_reg_read(_ARC_V2_MPU_EN) & (~AUX_MPU_RDP_ATTR_MASK);

	region_attr &= AUX_MPU_RDP_ATTR_MASK;
	z_arc_v2_aux_reg_write(_ARC_V2_MPU_EN, region_attr | val);
}

/**
 * @brief configure the MPU region
 *
 * @param index   MPU region index
 * @param base    base address
 * @param region_attr region attribute
 */
int arc_core_mpu_region(uint32_t index, uint32_t base, uint32_t size, uint32_t region_attr)
{
	if (index >= get_num_regions()) {
		return -EINVAL;
	}

	region_attr &= AUX_MPU_RDP_ATTR_MASK;

	_region_init(index, base, size, region_attr);

	return 0;
}

#if defined(CONFIG_USERSPACE)

/**
 * @brief configure MPU regions for the memory partitions of the memory domain
 *
 * @param thread the thread which has memory domain
 */
void arc_core_mpu_configure_mem_domain(struct k_thread *thread)
{
	int region_index = get_region_index_by_type(THREAD_DOMAIN_PARTITION_REGION);
	uint32_t num_partitions;
	struct k_mem_partition *pparts;
	struct k_mem_domain *mem_domain = NULL;

	if (thread) {
		mem_domain = thread->mem_domain_info.mem_domain;
	}

	if (mem_domain) {
		LOG_DBG("configure domain: %p", mem_domain);
		num_partitions = mem_domain->num_partitions;
		pparts = mem_domain->partitions;
	} else {
		LOG_DBG("disable domain partition regions");
		num_partitions = 0U;
		pparts = NULL;
	}

	for (; region_index >= 0; region_index--) {
		if (num_partitions) {
			LOG_DBG("set region 0x%x 0x%lx 0x%x",
				 region_index, pparts->start, pparts->size);
			_region_init(region_index, pparts->start, pparts->size, pparts->attr);
			num_partitions--;
		} else {
			/* clear the left mpu entries */
			_region_init(region_index, 0, 0, 0);
		}
		pparts++;
	}
}

/**
 * @brief remove MPU regions for the memory partitions of the memory domain
 *
 * @param mem_domain the target memory domain
 */
void arc_core_mpu_remove_mem_domain(struct k_mem_domain *mem_domain)
{
	ARG_UNUSED(mem_domain);

	int region_index = get_region_index_by_type(THREAD_DOMAIN_PARTITION_REGION);

	for (; region_index >= 0; region_index--) {
		_region_init(region_index, 0, 0, 0);
	}
}

/**
 * @brief reset MPU region for a single memory partition
 *
 * @param domain  the target memory domain
 * @param partition_id  memory partition id
 */
void arc_core_mpu_remove_mem_partition(struct k_mem_domain *domain, uint32_t part_id)
{
	ARG_UNUSED(domain);

	int region_index = get_region_index_by_type(THREAD_DOMAIN_PARTITION_REGION);

	LOG_DBG("disable region 0x%x", region_index + part_id);
	/* Disable region */
	_region_init(region_index + part_id, 0, 0, 0);
}

/**
 * @brief get the maximum number of free regions for memory domain partitions
 */
int arc_core_mpu_get_max_domain_partition_regions(void)
{
	return get_region_index_by_type(THREAD_DOMAIN_PARTITION_REGION) + 1;
}

/**
 * @brief validate the given buffer is user accessible or not
 */
int arc_core_mpu_buffer_validate(void *addr, size_t size, int write)
{
	/*
	 * For ARC MPU, smaller region number takes priority.
	 * we can stop the iteration immediately once we find the
	 * matched region that grants permission or denies access.
	 *
	 */
	for (int r_index = 0; r_index < get_num_regions(); r_index++) {
		if (!_is_enabled_region(r_index) || !_is_in_region(r_index, (uint32_t)addr, size)) {
			continue;
		}

		if (_is_user_accessible_region(r_index, write)) {
			return 0;
		} else {
			return -EPERM;
		}
	}

	return -EPERM;
}
#endif /* CONFIG_USERSPACE */

/* ARC MPU Driver Initial Setup */
/*
 * @brief MPU default initialization and configuration
 *
 * This function provides the default configuration mechanism for the Memory
 * Protection Unit (MPU).
 */
static int arc_mpu_init(const struct device *arg)
{
	ARG_UNUSED(arg);

	uint32_t num_regions = get_num_regions();

	if (mpu_config.num_regions > num_regions) {
		__ASSERT(0, "Request to configure: %u regions (supported: %u)\n",
			 mpu_config.num_regions, num_regions);
		return -EINVAL;
	}

	/* Disable MPU */
	arc_core_mpu_disable();

	/*
	 * the MPU regions are filled in the reverse order.
	 * According to ARCv2 ISA, the MPU region with smaller
	 * index has higher priority. The static background MPU
	 * regions in mpu_config will be in the bottom. Then
	 * the special type regions will be above.
	 */
	int r_index = num_regions - mpu_config.num_regions;

	/* clear all the regions first */
	for (uint32_t i = 0U; i < r_index; i++) {
		_region_init(i, 0, 0, 0);
	}

	/* configure the static regions */
	for (uint32_t i = 0U; i < mpu_config.num_regions; i++) {
		_region_init(r_index, mpu_config.mpu_regions[i].base,
			 mpu_config.mpu_regions[i].size, mpu_config.mpu_regions[i].attr);
		r_index++;
	}

	/* default region: no read, write and execute */
	arc_core_mpu_default(0);

	/* Enable MPU */
	arc_core_mpu_enable();

	return 0;
}

SYS_INIT(arc_mpu_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);

#endif /* ZEPHYR_ARCH_ARC_CORE_MPU_ARC_MPU_COMMON_INTERNAL_H_ */
