From 9bfc8d82d0c7bf97d646539cf718caf4ff06d781 Mon Sep 17 00:00:00 2001 From: Andrew Boie Date: Tue, 25 Aug 2020 14:42:33 -0700 Subject: [PATCH] userspace: introduce default memory domain We make a policy change here: all threads are members of a memory domain, never NULL. We introduce a default memory domain for threads that haven't been assigned to or inherited another one. Primary motivation for this change is better MMU support, as one common configuration will be to maintain page tables at the memory domain level. Signed-off-by: Andrew Boie --- include/app_memory/mem_domain.h | 15 ++++++++++++++- kernel/include/kswap.h | 2 +- kernel/mem_domain.c | 29 +++++++++++++---------------- kernel/thread.c | 8 +++----- 4 files changed, 31 insertions(+), 23 deletions(-) diff --git a/include/app_memory/mem_domain.h b/include/app_memory/mem_domain.h index c1946bca75e..845c8154d67 100644 --- a/include/app_memory/mem_domain.h +++ b/include/app_memory/mem_domain.h @@ -92,6 +92,18 @@ struct k_mem_domain { struct arch_mem_domain arch; #endif /* CONFIG_ARCH_MEM_DOMAIN_DATA */ }; + +/** + * Default memory domain + * + * All threads are a member of some memory domain, even if running in + * supervisor mode. Threads belong to this default memory domain if they + * haven't been added to or inherited membership from some other domain. + * + * This memory domain has the z_libc_partition partition for the C library + * added to it if exists. + */ +extern struct k_mem_domain k_mem_domain_default; #else /* To support use of IS_ENABLED for the APIs below */ struct k_mem_domain; @@ -164,7 +176,8 @@ extern void k_mem_domain_remove_partition(struct k_mem_domain *domain, /** * @brief Add a thread into a memory domain. * - * Add a thread into a memory domain. + * Add a thread into a memory domain. It will be removed from whatever + * memory domain it previously belonged to. * * @param domain The memory domain that the thread is going to be added into. * @param thread ID of thread going to be added into the memory domain. diff --git a/kernel/include/kswap.h b/kernel/include/kswap.h index 7a0b42f17fb..8bf5721eb36 100644 --- a/kernel/include/kswap.h +++ b/kernel/include/kswap.h @@ -197,7 +197,7 @@ static inline void z_dummy_thread_init(struct k_thread *dummy_thread) dummy_thread->stack_info.size = 0U; #endif #ifdef CONFIG_USERSPACE - dummy_thread->mem_domain_info.mem_domain = 0; + dummy_thread->mem_domain_info.mem_domain = &k_mem_domain_default; #endif _current_cpu->current = dummy_thread; diff --git a/kernel/mem_domain.c b/kernel/mem_domain.c index 1589ad4f12e..97f3e10532f 100644 --- a/kernel/mem_domain.c +++ b/kernel/mem_domain.c @@ -11,6 +11,7 @@ #include #include #include +#include #define LOG_LEVEL CONFIG_KERNEL_LOG_LEVEL #include @@ -19,6 +20,8 @@ LOG_MODULE_DECLARE(os); static struct k_spinlock lock; static uint8_t max_partitions; +struct k_mem_domain k_mem_domain_default; + #if __ASSERT_ON static bool check_add_partition(struct k_mem_domain *domain, struct k_mem_partition *part) @@ -225,12 +228,12 @@ void k_mem_domain_add_thread(struct k_mem_domain *domain, k_tid_t thread) __ASSERT_NO_MSG(domain != NULL); __ASSERT_NO_MSG(thread != NULL); - __ASSERT(thread->mem_domain_info.mem_domain == NULL, - "thread %p belongs to a different memory domain %p", - thread, thread->mem_domain_info.mem_domain); key = k_spin_lock(&lock); - + if (thread->mem_domain_info.mem_domain != NULL) { + sys_dlist_remove(&thread->mem_domain_info.mem_domain_q_node); + arch_mem_domain_thread_remove(thread); + } sys_dlist_append(&domain->mem_domain_q, &thread->mem_domain_info.mem_domain_q_node); thread->mem_domain_info.mem_domain = domain; @@ -242,18 +245,7 @@ void k_mem_domain_add_thread(struct k_mem_domain *domain, k_tid_t thread) void k_mem_domain_remove_thread(k_tid_t thread) { - k_spinlock_key_t key; - - __ASSERT_NO_MSG(thread != NULL); - __ASSERT(thread->mem_domain_info.mem_domain != NULL, - "thread does not belong to a memory domain"); - - key = k_spin_lock(&lock); - 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); + k_mem_domain_add_thread(&k_mem_domain_default, thread); } static int init_mem_domain_module(struct device *arg) @@ -268,6 +260,11 @@ static int init_mem_domain_module(struct device *arg) */ __ASSERT(max_partitions <= CONFIG_MAX_DOMAIN_PARTITIONS, ""); + k_mem_domain_init(&k_mem_domain_default, 0, NULL); +#ifdef Z_LIBC_PARTITION_EXISTS + k_mem_domain_add_partition(&k_mem_domain_default, &z_libc_partition); +#endif /* Z_LIBC_PARTITION_EXISTS */ + return 0; } diff --git a/kernel/thread.c b/kernel/thread.c index e8050b23524..1bbffd8dd19 100644 --- a/kernel/thread.c +++ b/kernel/thread.c @@ -537,7 +537,6 @@ char *z_setup_new_thread(struct k_thread *new_thread, z_object_init(new_thread); z_object_init(stack); new_thread->stack_obj = stack; - new_thread->mem_domain_info.mem_domain = NULL; new_thread->syscall_frame = NULL; /* Any given thread has access to itself */ @@ -601,10 +600,9 @@ char *z_setup_new_thread(struct k_thread *new_thread, #endif #ifdef CONFIG_USERSPACE /* New threads inherit any memory domain membership by the parent */ - if (_current->mem_domain_info.mem_domain != NULL) { - k_mem_domain_add_thread(_current->mem_domain_info.mem_domain, - new_thread); - } + new_thread->mem_domain_info.mem_domain = NULL; + k_mem_domain_add_thread(_current->mem_domain_info.mem_domain, + new_thread); if ((options & K_INHERIT_PERMS) != 0U) { z_thread_perms_inherit(_current, new_thread);