<commit_before>/*
 * Copyright (c) 2017 Linaro Limited.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <device.h>
#include <init.h>
#include <kernel.h>
#include <soc.h>
#include <arch/arm/cortex_m/cmsis.h>
#include <arch/arm/cortex_m/mpu/arm_mpu.h>
#include <arch/arm/cortex_m/mpu/arm_core_mpu.h>
#include <logging/sys_log.h>
#include <linker/linker-defs.h>

#define ARM_MPU_DEV ((volatile struct arm_mpu *) ARM_MPU_BASE)

/* ARM MPU Enabled state */
static u8_t arm_mpu_enabled;

/**
 * The attributes referenced in this function are described at:
 * https://goo.gl/hMry3r
 * This function is private to the driver.
 */
static inline u32_t _get_region_attr(u32_t xn, u32_t ap, u32_t tex,
				     u32_t c, u32_t b, u32_t s,
				     u32_t srd, u32_t size)
{
	return ((xn << 28) | (ap) | (tex << 19) | (s << 18)
		| (c << 17) | (b << 16) | (srd << 8) | (size));
}

/**
 * This internal function converts the region size to
 * the SIZE field value of MPU_RASR.
 */
static inline u32_t _size_to_mpu_rasr_size(u32_t size)
{
	/* The minimal supported region size is 32 bytes */
	if (size <= 32) {
		return REGION_32B;
	}

	/*
	 * A size value greater than 2^31 could not be handled by
	 * round_up_to_next_power_of_two() properly. We handle
	 * it separately here.
	 */
	if (size > (1 << 31)) {
		return REGION_4G;
	}

	size = 1 << (32 - __builtin_clz(size - 1));
	return (32 - __builtin_clz(size) - 2) << 1;
}


/**
 * This internal function is utilized by the MPU driver to parse the intent
 * type (i.e. THREAD_STACK_REGION) and return the correct parameter set.
 */
static inline u32_t _get_region_attr_by_type(u32_t type, u32_t size)
{
	int region_size = _size_to_mpu_rasr_size(size);

	switch (type) {
	case THREAD_STACK_USER_REGION:
		return _get_region_attr(1, P_RW_U_RW, 0, 1, 0,
					1, 0, region_size);
	case THREAD_STACK_REGION:
		return _get_region_attr(1, P_RW_U_RW, 0, 1, 0,
					1, 0, region_size);
	case THREAD_STACK_GUARD_REGION:
		return _get_region_attr(1, P_RO_U_NA, 0, 1, 0,
					1, 0, region_size);
	case THREAD_APP_DATA_REGION:
		return _get_region_attr(1, P_RW_U_RW, 0, 1, 0,
					1, 0, region_size);
	default:
		/* Size 0 region */
		return 0;
	}
}

static inline u8_t _get_num_regions(void)
{
	u32_t type = ARM_MPU_DEV->type;

	type = (type & 0xFF00) >> 8;

	return (u8_t)type;
}

static void _region_init(u32_t index, u32_t region_addr,
			 u32_t region_attr)
{
	/* Select the region you want to access */
	ARM_MPU_DEV->rnr = index;
	/* Configure the region */
	ARM_MPU_DEV->rbar = (region_addr & REGION_BASE_ADDR_MASK)
				| REGION_VALID | index;
	ARM_MPU_DEV->rasr = region_attr | REGION_ENABLE;
	SYS_LOG_DBG("[%d] 0x%08x 0x%08x", index, region_addr, region_attr);
}

/**
 * This internal function is utilized by the MPU driver to parse the intent
 * type (i.e. THREAD_STACK_REGION) and return the correct region index.
 */
static inline u32_t _get_region_index_by_type(u32_t type)
{
	/*
	 * The new MPU regions are allocated per type after the statically
	 * configured regions. The type is one-indexed rather than
	 * zero-indexed, therefore we need to subtract by one to get the region
	 * index.
	 */
	switch (type) {
	case THREAD_STACK_USER_REGION:
		return mpu_config.num_regions + THREAD_STACK_REGION - 1;
	case THREAD_STACK_REGION:
	case THREAD_STACK_GUARD_REGION:
	case THREAD_APP_DATA_REGION:
		return mpu_config.num_regions + type - 1;
	case THREAD_DOMAIN_PARTITION_REGION:
#if defined(CONFIG_USERSPACE)
		return mpu_config.num_regions + type - 1;
#elif defined(CONFIG_MPU_STACK_GUARD)
		return mpu_config.num_regions + type - 2;
#else
		/*
		 * Start domain partition region from stack guard region
		 * since stack guard is not enabled.
		 */
		return mpu_config.num_regions + type - 3;
#endif
	default:
		__ASSERT(0, "Unsupported type");
		return 0;
	}
}

/**
 * This internal function checks if region is enabled or not.
 */
static inline int _is_enabled_region(u32_t r_index)
{
	ARM_MPU_DEV->rnr = r_index;

	return ARM_MPU_DEV->rasr & REGION_ENABLE_MASK;
}

/**
 * This internal function checks if the given buffer is in the region.
 */
static inline int _is_in_region(u32_t r_index, u32_t start, u32_t size)
{
	u32_t r_addr_start;
	u32_t r_size_lshift;
	u32_t r_addr_end;

	ARM_MPU_DEV->rnr = r_index;
	r_addr_start = ARM_MPU_DEV->rbar & REGION_BASE_ADDR_MASK;
	r_size_lshift = ((ARM_MPU_DEV->rasr & REGION_SIZE_MASK) >>
			REGION_SIZE_OFFSET) + 1;
	r_addr_end = r_addr_start + (1 << r_size_lshift) - 1;

	if (start >= r_addr_start && (start + size - 1) <= r_addr_end) {
		return 1;
	}

	return 0;
}

/**
 * This internal function checks if the region is user accessible or not.
 */
static inline int _is_user_accessible_region(u32_t r_index, int write)
{
	u32_t r_ap;

	ARM_MPU_DEV->rnr = r_index;
	r_ap = ARM_MPU_DEV->rasr & ACCESS_PERMS_MASK;

	/* always return true if this is the thread stack region */
	if (_get_region_index_by_type(THREAD_STACK_REGION) == r_index) {
		return 1;
	}

	if (write) {
		return r_ap == P_RW_U_RW;
	}
<commit_msg>arch: arm: enhance internal function documentation<commit_after>/*
 * Copyright (c) 2017 Linaro Limited.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <device.h>
#include <init.h>
#include <kernel.h>
#include <soc.h>
#include <arch/arm/cortex_m/cmsis.h>
#include <arch/arm/cortex_m/mpu/arm_mpu.h>
#include <arch/arm/cortex_m/mpu/arm_core_mpu.h>
#include <logging/sys_log.h>
#include <linker/linker-defs.h>

#define ARM_MPU_DEV ((volatile struct arm_mpu *) ARM_MPU_BASE)

/* ARM MPU Enabled state */
static u8_t arm_mpu_enabled;

/**
 * The attributes referenced in this function are described at:
 * https://goo.gl/hMry3r
 * This function is private to the driver.
 */
static inline u32_t _get_region_attr(u32_t xn, u32_t ap, u32_t tex,
				     u32_t c, u32_t b, u32_t s,
				     u32_t srd, u32_t size)
{
	return ((xn << 28) | (ap) | (tex << 19) | (s << 18)
		| (c << 17) | (b << 16) | (srd << 8) | (size));
}

/**
 * This internal function converts the region size to
 * the SIZE field value of MPU_RASR.
 */
static inline u32_t _size_to_mpu_rasr_size(u32_t size)
{
	/* The minimal supported region size is 32 bytes */
	if (size <= 32) {
		return REGION_32B;
	}

	/*
	 * A size value greater than 2^31 could not be handled by
	 * round_up_to_next_power_of_two() properly. We handle
	 * it separately here.
	 */
	if (size > (1 << 31)) {
		return REGION_4G;
	}

	size = 1 << (32 - __builtin_clz(size - 1));
	return (32 - __builtin_clz(size) - 2) << 1;
}


/**
 * This internal function is utilized by the MPU driver to parse the intent
 * type (i.e. THREAD_STACK_REGION) and return the correct parameter set.
 */
static inline u32_t _get_region_attr_by_type(u32_t type, u32_t size)
{
	int region_size = _size_to_mpu_rasr_size(size);

	switch (type) {
	case THREAD_STACK_USER_REGION:
		return _get_region_attr(1, P_RW_U_RW, 0, 1, 0,
					1, 0, region_size);
	case THREAD_STACK_REGION:
		return _get_region_attr(1, P_RW_U_RW, 0, 1, 0,
					1, 0, region_size);
	case THREAD_STACK_GUARD_REGION:
		return _get_region_attr(1, P_RO_U_NA, 0, 1, 0,
					1, 0, region_size);
	case THREAD_APP_DATA_REGION:
		return _get_region_attr(1, P_RW_U_RW, 0, 1, 0,
					1, 0, region_size);
	default:
		/* Size 0 region */
		return 0;
	}
}

static inline u8_t _get_num_regions(void)
{
	u32_t type = ARM_MPU_DEV->type;

	type = (type & 0xFF00) >> 8;

	return (u8_t)type;
}

/* This internal function performs MPU region initialization.
 *
 * Note:
 *   The caller is responsible to supply a valid region index.
 */
static void _region_init(u32_t index, u32_t region_addr,
			 u32_t region_attr)
{
	/* Select the region you want to access */
	ARM_MPU_DEV->rnr = index;
	/* Configure the region */
	ARM_MPU_DEV->rbar = (region_addr & REGION_BASE_ADDR_MASK)
				| REGION_VALID | index;
	ARM_MPU_DEV->rasr = region_attr | REGION_ENABLE;
	SYS_LOG_DBG("[%d] 0x%08x 0x%08x", index, region_addr, region_attr);
}

/**
 * This internal function is utilized by the MPU driver to parse the intent
 * type (i.e. THREAD_STACK_REGION) and return the correct region index.
 */
static inline u32_t _get_region_index_by_type(u32_t type)
{
	/*
	 * The new MPU regions are allocated per type after the statically
	 * configured regions. The type is one-indexed rather than
	 * zero-indexed, therefore we need to subtract by one to get the region
	 * index.
	 */
	switch (type) {
	case THREAD_STACK_USER_REGION:
		return mpu_config.num_regions + THREAD_STACK_REGION - 1;
	case THREAD_STACK_REGION:
	case THREAD_STACK_GUARD_REGION:
	case THREAD_APP_DATA_REGION:
		return mpu_config.num_regions + type - 1;
	case THREAD_DOMAIN_PARTITION_REGION:
#if defined(CONFIG_USERSPACE)
		return mpu_config.num_regions + type - 1;
#elif defined(CONFIG_MPU_STACK_GUARD)
		return mpu_config.num_regions + type - 2;
#else
		/*
		 * Start domain partition region from stack guard region
		 * since stack guard is not enabled.
		 */
		return mpu_config.num_regions + type - 3;
#endif
	default:
		__ASSERT(0, "Unsupported type");
		return 0;
	}
}

/**
 * This internal function checks if region is enabled or not.
 *
 * Note:
 *   The caller must provide a valid region number.
 */
static inline int _is_enabled_region(u32_t r_index)
{
	ARM_MPU_DEV->rnr = r_index;

	return ARM_MPU_DEV->rasr & REGION_ENABLE_MASK;
}

/**
 * This internal function checks if the given buffer is in the region.
 *
 * Note:
 *   The caller must provide a valid region number.
 */
static inline int _is_in_region(u32_t r_index, u32_t start, u32_t size)
{
	u32_t r_addr_start;
	u32_t r_size_lshift;
	u32_t r_addr_end;

	ARM_MPU_DEV->rnr = r_index;
	r_addr_start = ARM_MPU_DEV->rbar & REGION_BASE_ADDR_MASK;
	r_size_lshift = ((ARM_MPU_DEV->rasr & REGION_SIZE_MASK) >>
			REGION_SIZE_OFFSET) + 1;
	r_addr_end = r_addr_start + (1 << r_size_lshift) - 1;

	if (start >= r_addr_start && (start + size - 1) <= r_addr_end) {
		return 1;
	}

	return 0;
}

/**
 * This internal function checks if the region is user accessible or not.
 *
 * Note:
 *   The caller must provide a valid region number.
 */
static inline int _is_user_accessible_region(u32_t r_index, int write)
{
	u32_t r_ap;

	ARM_MPU_DEV->rnr = r_index;
	r_ap = ARM_MPU_DEV->rasr & ACCESS_PERMS_MASK;

	/* always return true if this is the thread stack region */
	if (_get_region_index_by_type(THREAD_STACK_REGION) == r_index) {
		return 1;
	}

	if (write) {
		return r_ap == P_RW_U_RW;
	}

{'fraction_non_alphanumeric': 0.10810028929604629, 'fraction_numerical': 0.02892960462873674, 'mean_word_length': 3.908187411263606, 'pattern_counts': {'":': 0, '<': 65, '<?xml version=': 0, '>': 55, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7642108', 'n_tokens_mistral': 4421, 'n_tokens_neox': 4074, 'n_words': 1096}