diff --git a/arch/arc/core/mpu/arc_core_mpu.c b/arch/arc/core/mpu/arc_core_mpu.c index 383e4bdb4ae..a644a81180d 100644 --- a/arch/arc/core/mpu/arc_core_mpu.c +++ b/arch/arc/core/mpu/arc_core_mpu.c @@ -9,6 +9,7 @@ #include #include #include +#include /* * @brief Configure MPU for the thread @@ -37,6 +38,10 @@ int z_arch_mem_domain_max_partitions_get(void) void z_arch_mem_domain_partition_remove(struct k_mem_domain *domain, u32_t partition_id) { + if (_current->mem_domain_info.mem_domain != domain) { + return; + } + arc_core_mpu_disable(); arc_core_mpu_remove_mem_partition(domain, partition_id); arc_core_mpu_enable(); @@ -45,8 +50,12 @@ void z_arch_mem_domain_partition_remove(struct k_mem_domain *domain, /* * Configure MPU memory domain */ -void z_arch_mem_domain_configure(struct k_thread *thread) +void z_arch_mem_domain_thread_add(struct k_thread *thread) { + if (_current != thread) { + return; + } + arc_core_mpu_disable(); arc_core_mpu_configure_mem_domain(thread); arc_core_mpu_enable(); @@ -57,6 +66,10 @@ void z_arch_mem_domain_configure(struct k_thread *thread) */ void z_arch_mem_domain_destroy(struct k_mem_domain *domain) { + if (_current->mem_domain_info.mem_domain != domain) { + return; + } + arc_core_mpu_disable(); arc_core_mpu_remove_mem_domain(domain); arc_core_mpu_enable(); @@ -68,6 +81,15 @@ void z_arch_mem_domain_partition_add(struct k_mem_domain *domain, /* No-op on this architecture */ } +void z_arch_mem_domain_thread_remove(struct k_thread *thread) +{ + if (_current != thread) { + return; + } + + z_arch_mem_domain_destroy(thread->mem_domain_info.mem_domain); +} + /* * Validate the given buffer is user accessible or not */ diff --git a/arch/arm/core/cortex_m/mpu/arm_core_mpu.c b/arch/arm/core/cortex_m/mpu/arm_core_mpu.c index 8009d158f4a..b2f8a943bb2 100644 --- a/arch/arm/core/cortex_m/mpu/arm_core_mpu.c +++ b/arch/arm/core/cortex_m/mpu/arm_core_mpu.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "arm_core_mpu_dev.h" #include @@ -282,8 +283,12 @@ int z_arch_mem_domain_max_partitions_get(void) /** * @brief Configure the memory domain of the thread. */ -void z_arch_mem_domain_configure(struct k_thread *thread) +void z_arch_mem_domain_thread_add(struct k_thread *thread) { + if (_current != thread) { + return; + } + /* Request to configure memory domain for a thread. * This triggers re-programming of the entire dynamic * memory map. @@ -304,6 +309,11 @@ void z_arch_mem_domain_destroy(struct k_mem_domain *domain) */ int i; struct k_mem_partition partition; + + if (_current->mem_domain_info.mem_domain != domain) { + return; + } + /* Partitions belonging to the memory domain will be reset * to default (Privileged RW, Unprivileged NA) permissions. */ @@ -338,6 +348,10 @@ void z_arch_mem_domain_partition_remove(struct k_mem_domain *domain, */ k_mem_partition_attr_t reset_attr = K_MEM_PARTITION_P_RW_U_NA; + if (_current->mem_domain_info.mem_domain != domain) { + return; + } + arm_core_mpu_mem_partition_config_update( &domain->partitions[partition_id], &reset_attr); } @@ -348,6 +362,15 @@ void z_arch_mem_domain_partition_add(struct k_mem_domain *domain, /* No-op on this architecture */ } +void z_arch_mem_domain_thread_remove(struct k_thread *thread) +{ + if (_current != thread) { + return; + } + + z_arch_mem_domain_destroy(thread->mem_domain_info.mem_domain); +} + /* * Validate the given buffer is user accessible or not */ diff --git a/arch/x86/core/ia32/thread.c b/arch/x86/core/ia32/thread.c index 2b8769f1a04..e93c8717cc9 100644 --- a/arch/x86/core/ia32/thread.c +++ b/arch/x86/core/ia32/thread.c @@ -159,8 +159,10 @@ void _x86_swap_update_page_tables(struct k_thread *incoming, /* Ensure that the outgoing mem domain configuration * is set back to default state. */ - z_arch_mem_domain_destroy(outgoing->mem_domain_info.mem_domain); - z_arch_mem_domain_configure(incoming); + z_x86_mem_domain_pages_update(outgoing->mem_domain_info.mem_domain, + X86_MEM_DOMAIN_RESET_PAGES); + z_x86_mem_domain_pages_update(incoming->mem_domain_info.mem_domain, + X86_MEM_DOMAIN_SET_PAGES); } } diff --git a/arch/x86/core/ia32/x86_mmu.c b/arch/x86/core/ia32/x86_mmu.c index 1332e31e860..c262744055c 100644 --- a/arch/x86/core/ia32/x86_mmu.c +++ b/arch/x86/core/ia32/x86_mmu.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -377,12 +378,9 @@ static inline void activate_partition(struct k_mem_partition *partition) partition->size, attr, mask); } -/* Helper macros needed to be passed to x86_update_mem_domain_pages */ -#define X86_MEM_DOMAIN_SET_PAGES (0U) -#define X86_MEM_DOMAIN_RESET_PAGES (1U) /* Pass 1 to page_conf if reset of mem domain pages is needed else pass a 0*/ -static inline void x86_mem_domain_pages_update(struct k_mem_domain *mem_domain, - u32_t page_conf) +void z_x86_mem_domain_pages_update(struct k_mem_domain *mem_domain, + u32_t page_conf) { u32_t partition_index; u32_t total_partitions; @@ -424,10 +422,14 @@ out: } /* Load the partitions of the thread. */ -void z_arch_mem_domain_configure(struct k_thread *thread) +void z_arch_mem_domain_thread_add(struct k_thread *thread) { - x86_mem_domain_pages_update(thread->mem_domain_info.mem_domain, - X86_MEM_DOMAIN_SET_PAGES); + if (_current != thread) { + return; + } + + z_x86_mem_domain_pages_update(thread->mem_domain_info.mem_domain, + X86_MEM_DOMAIN_SET_PAGES); } /* Destroy or reset the mmu page tables when necessary. @@ -435,7 +437,20 @@ void z_arch_mem_domain_configure(struct k_thread *thread) */ void z_arch_mem_domain_destroy(struct k_mem_domain *domain) { - x86_mem_domain_pages_update(domain, X86_MEM_DOMAIN_RESET_PAGES); + if (_current->mem_domain_info.mem_domain != domain) { + return; + } + + z_x86_mem_domain_pages_update(domain, X86_MEM_DOMAIN_RESET_PAGES); +} + +void z_arch_mem_domain_thread_remove(struct k_thread *thread) +{ + if (_current != thread) { + return; + } + + z_arch_mem_domain_destroy(thread->mem_domain_info.mem_domain); } /* Reset/destroy one partition specified in the argument of the API. */ @@ -444,6 +459,10 @@ void z_arch_mem_domain_partition_remove(struct k_mem_domain *domain, { struct k_mem_partition *partition; + if (_current->mem_domain_info.mem_domain != domain) { + return; + } + __ASSERT_NO_MSG(domain != NULL); __ASSERT(partition_id <= domain->num_partitions, "invalid partitions"); @@ -458,6 +477,10 @@ void z_arch_mem_domain_partition_add(struct k_mem_domain *domain, { struct k_mem_partition *partition; + if (_current->mem_domain_info.mem_domain != domain) { + return; + } + __ASSERT_NO_MSG(domain != NULL); __ASSERT(partition_id <= domain->num_partitions, "invalid partitions"); diff --git a/arch/x86/include/ia32/kernel_arch_func.h b/arch/x86/include/ia32/kernel_arch_func.h index eeca9b122cb..fa73cfd2470 100644 --- a/arch/x86/include/ia32/kernel_arch_func.h +++ b/arch/x86/include/ia32/kernel_arch_func.h @@ -81,6 +81,13 @@ extern FUNC_NORETURN void z_x86_userspace_enter(k_thread_entry_t user_entry, u32_t stack_end, u32_t stack_start); +/* Helper macros needed to be passed to x86_update_mem_domain_pages */ +#define X86_MEM_DOMAIN_SET_PAGES (0U) +#define X86_MEM_DOMAIN_RESET_PAGES (1U) + +extern void z_x86_mem_domain_pages_update(struct k_mem_domain *mem_domain, + u32_t page_conf); + #include /* For size_t */ #ifdef __cplusplus diff --git a/kernel/include/kernel_internal.h b/kernel/include/kernel_internal.h index e239a0169ca..5ea53c0b6a6 100644 --- a/kernel/include/kernel_internal.h +++ b/kernel/include/kernel_internal.h @@ -73,40 +73,48 @@ extern int z_arch_float_disable(struct k_thread *thread); /** * @brief Get the maximum number of partitions for a memory domain * - * A memory domain is a container data structure containing some number of - * memory partitions, where each partition represents a memory range with - * access policies. - * - * MMU-based systems don't have a limit here, but MPU-based systems will - * have an upper bound on how many different regions they can manage - * simultaneously. - * - * @return Max number of free regions, or -1 if there is no limit + * @return Max number of partitions, or -1 if there is no limit */ extern int z_arch_mem_domain_max_partitions_get(void); /** - * @brief Configure the memory domain of the thread. + * @brief Add a thread to a memory domain (arch-specific) * - * A memory domain is a container data structure containing some number of - * memory partitions, where each partition represents a memory range with - * access policies. This api will configure the appropriate hardware - * registers to make it work. + * Architecture-specific hook to manage internal data structures or hardware + * state when the provided thread has been added to a memory domain. + * + * The thread's memory domain pointer will be set to the domain to be added + * to. * * @param thread Thread which needs to be configured. */ -extern void z_arch_mem_domain_configure(struct k_thread *thread); +extern void z_arch_mem_domain_thread_add(struct k_thread *thread); /** - * @brief Remove a partition from the memory domain + * @brief Remove a thread from a memory domain (arch-specific) * - * A memory domain contains multiple partitions and this API provides the - * freedom to remove a particular partition while keeping others intact. - * This API will handle any arch/HW specific changes that needs to be done. - * Only called if the active thread's domain was modified. + * Architecture-specific hook to manage internal data structures or hardware + * state when the provided thread has been removed from a memory domain. + * + * The thread's memory domain pointer will be the domain that the thread + * is being removed from. + * + * @param thread Thread being removed from its memory domain + */ +extern void z_arch_mem_domain_thread_remove(struct k_thread *thread); + +/** + * @brief Remove a partition from the memory domain (arch-specific) + * + * Architecture-specific hook to manage internal data structures or hardware + * state when a memory domain has had a partition removed. + * + * The partition index data, and the number of partitions configured, are not + * respectively cleared and decremented in the domain until after this function + * runs. * * @param domain The memory domain structure - * @param partition_id The partition that needs to be deleted + * @param partition_id The partition index that needs to be deleted */ extern void z_arch_mem_domain_partition_remove(struct k_mem_domain *domain, u32_t partition_id); @@ -114,10 +122,8 @@ extern void z_arch_mem_domain_partition_remove(struct k_mem_domain *domain, /** * @brief Add a partition to the memory domain * - * A memory domain contains multiple partitions and this API provides the - * freedom to add an additional partition to a memory domain. - * This API will handle any arch/HW specific changes that needs to be done. - * Only called if the active thread's domain was modified. + * Architecture-specific hook to manage internal data structures or hardware + * state when a memory domain has a partition added. * * @param domain The memory domain structure * @param partition_id The partition that needs to be added @@ -128,9 +134,11 @@ extern void z_arch_mem_domain_partition_add(struct k_mem_domain *domain, /** * @brief Remove the memory domain * - * A memory domain contains multiple partitions and this API will traverse - * all these to reset them back to default setting. - * This API will handle any arch/HW specific changes that needs to be done. + * Architecture-specific hook to manage internal data structures or hardware + * state when a memory domain has been destroyed. + * + * Thread assignments to the memory domain are only cleared after this function + * runs. * * @param domain The memory domain structure which needs to be deleted. */ diff --git a/kernel/mem_domain.c b/kernel/mem_domain.c index 841d008826f..c91d9df9f1f 100644 --- a/kernel/mem_domain.c +++ b/kernel/mem_domain.c @@ -129,12 +129,7 @@ void k_mem_domain_destroy(struct k_mem_domain *domain) 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); - } + z_arch_mem_domain_destroy(domain); SYS_DLIST_FOR_EACH_NODE_SAFE(&domain->mem_domain_q, node, next_node) { struct k_thread *thread = @@ -181,13 +176,7 @@ void k_mem_domain_add_partition(struct k_mem_domain *domain, domain->num_partitions++; - /* Handle architecture-specific add - * only if it is the current thread. - */ - if (_current->mem_domain_info.mem_domain == domain) { - z_arch_mem_domain_partition_add(domain, p_idx); - } - + z_arch_mem_domain_partition_add(domain, p_idx); k_spin_unlock(&lock, key); } @@ -213,12 +202,7 @@ void k_mem_domain_remove_partition(struct k_mem_domain *domain, /* 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); - } + z_arch_mem_domain_partition_remove(domain, p_idx); /* A zero-sized partition denotes it's a free partition */ domain->partitions[p_idx].size = 0U; @@ -243,9 +227,7 @@ void k_mem_domain_add_thread(struct k_mem_domain *domain, k_tid_t thread) &thread->mem_domain_info.mem_domain_q_node); thread->mem_domain_info.mem_domain = domain; - if (_current == thread) { - z_arch_mem_domain_configure(thread); - } + z_arch_mem_domain_thread_add(thread); k_spin_unlock(&lock, key); } @@ -258,13 +240,10 @@ void k_mem_domain_remove_thread(k_tid_t thread) __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); - } + z_arch_mem_domain_thread_remove(thread); sys_dlist_remove(&thread->mem_domain_info.mem_domain_q_node); thread->mem_domain_info.mem_domain = NULL; - k_spin_unlock(&lock, key); }