1 /* 2 * Copyright (c) 2017 Linaro Limited 3 * Copyright (c) 2018-2020 Intel Corporation 4 * 5 * SPDX-License-Identifier: Apache-2.0 6 */ 7 8 #ifndef INCLUDE_APP_MEMORY_MEM_DOMAIN_H 9 #define INCLUDE_APP_MEMORY_MEM_DOMAIN_H 10 11 #include <stdint.h> 12 #include <stddef.h> 13 #include <zephyr/sys/dlist.h> 14 #include <zephyr/toolchain.h> 15 #include <zephyr/kernel/thread.h> 16 17 #ifdef __cplusplus 18 extern "C" { 19 #endif 20 21 /** 22 * @defgroup mem_domain_apis Memory domain APIs 23 * @ingroup kernel_apis 24 * @{ 25 */ 26 27 #ifdef CONFIG_USERSPACE 28 /** 29 * @def K_MEM_PARTITION_DEFINE 30 * 31 * @brief Statically declare a memory partition 32 */ 33 #ifdef _ARCH_MEM_PARTITION_ALIGN_CHECK 34 #define K_MEM_PARTITION_DEFINE(name, start, size, attr) \ 35 _ARCH_MEM_PARTITION_ALIGN_CHECK(start, size); \ 36 struct k_mem_partition name =\ 37 { (uintptr_t)start, size, attr} 38 #else 39 #define K_MEM_PARTITION_DEFINE(name, start, size, attr) \ 40 struct k_mem_partition name =\ 41 { (uintptr_t)start, size, attr} 42 #endif /* _ARCH_MEM_PARTITION_ALIGN_CHECK */ 43 44 /** 45 * @brief Memory Partition 46 * 47 * A memory partition is a region of memory in the linear address space 48 * with a specific access policy. 49 * 50 * The alignment of the starting address, and the alignment of the size 51 * value may have varying requirements based on the capabilities of the 52 * underlying memory management hardware; arbitrary values are unlikely 53 * to work. 54 */ 55 struct k_mem_partition { 56 /** start address of memory partition */ 57 uintptr_t start; 58 /** size of memory partition */ 59 size_t size; 60 /** attribute of memory partition */ 61 k_mem_partition_attr_t attr; 62 }; 63 64 /** 65 * @brief Memory Domain 66 * 67 * A memory domain is a collection of memory partitions, used to represent 68 * a user thread's access policy for the linear address space. A thread 69 * may be a member of only one memory domain, but any memory domain may 70 * have multiple threads that are members. 71 * 72 * Supervisor threads may also be a member of a memory domain; this has 73 * no implications on their memory access but can be useful as any child 74 * threads inherit the memory domain membership of the parent. 75 * 76 * A user thread belonging to a memory domain with no active partitions 77 * will have guaranteed access to its own stack buffer, program text, 78 * and read-only data. 79 */ 80 struct k_mem_domain { 81 #ifdef CONFIG_ARCH_MEM_DOMAIN_DATA 82 struct arch_mem_domain arch; 83 #endif /* CONFIG_ARCH_MEM_DOMAIN_DATA */ 84 /** partitions in the domain */ 85 struct k_mem_partition partitions[CONFIG_MAX_DOMAIN_PARTITIONS]; 86 /** Doubly linked list of member threads */ 87 sys_dlist_t mem_domain_q; 88 /** number of active partitions in the domain */ 89 uint8_t num_partitions; 90 }; 91 92 /** 93 * Default memory domain 94 * 95 * All threads are a member of some memory domain, even if running in 96 * supervisor mode. Threads belong to this default memory domain if they 97 * haven't been added to or inherited membership from some other domain. 98 * 99 * This memory domain has the z_libc_partition partition for the C library 100 * added to it if exists. 101 */ 102 extern struct k_mem_domain k_mem_domain_default; 103 #else 104 /* To support use of IS_ENABLED for the APIs below */ 105 struct k_mem_domain; 106 struct k_mem_partition; 107 #endif /* CONFIG_USERSPACE */ 108 109 /** 110 * @brief Initialize a memory domain. 111 * 112 * Initialize a memory domain with given name and memory partitions. 113 * 114 * See documentation for k_mem_domain_add_partition() for details about 115 * partition constraints. 116 * 117 * Do not call k_mem_domain_init() on the same memory domain more than once, 118 * doing so is undefined behavior. 119 * 120 * @param domain The memory domain to be initialized. 121 * @param num_parts The number of array items of "parts" parameter. 122 * @param parts An array of pointers to the memory partitions. Can be NULL 123 * if num_parts is zero. 124 * 125 * @retval 0 if successful 126 * @retval -EINVAL if invalid parameters supplied 127 * @retval -ENOMEM if insufficient memory 128 */ 129 int k_mem_domain_init(struct k_mem_domain *domain, uint8_t num_parts, 130 struct k_mem_partition *parts[]); 131 132 /** 133 * @brief Add a memory partition into a memory domain. 134 * 135 * Add a memory partition into a memory domain. Partitions must conform to 136 * the following constraints: 137 * 138 * - Partitions in the same memory domain may not overlap each other. 139 * - Partitions must not be defined which expose private kernel 140 * data structures or kernel objects. 141 * - The starting address alignment, and the partition size must conform to 142 * the constraints of the underlying memory management hardware, which 143 * varies per architecture. 144 * - Memory domain partitions are only intended to control access to memory 145 * from user mode threads. 146 * - If CONFIG_EXECUTE_XOR_WRITE is enabled, the partition must not allow 147 * both writes and execution. 148 * 149 * Violating these constraints may lead to CPU exceptions or undefined 150 * behavior. 151 * 152 * @param domain The memory domain to be added a memory partition. 153 * @param part The memory partition to be added 154 * 155 * @retval 0 if successful 156 * @retval -EINVAL if invalid parameters supplied 157 * @retval -ENOSPC if no free partition slots available 158 */ 159 int k_mem_domain_add_partition(struct k_mem_domain *domain, 160 struct k_mem_partition *part); 161 162 /** 163 * @brief Remove a memory partition from a memory domain. 164 * 165 * Remove a memory partition from a memory domain. 166 * 167 * @param domain The memory domain to be removed a memory partition. 168 * @param part The memory partition to be removed 169 * 170 * @retval 0 if successful 171 * @retval -EINVAL if invalid parameters supplied 172 * @retval -ENOENT if no matching partition found 173 */ 174 int k_mem_domain_remove_partition(struct k_mem_domain *domain, 175 struct k_mem_partition *part); 176 177 /** 178 * @brief Add a thread into a memory domain. 179 * 180 * Add a thread into a memory domain. It will be removed from whatever 181 * memory domain it previously belonged to. 182 * 183 * @param domain The memory domain that the thread is going to be added into. 184 * @param thread ID of thread going to be added into the memory domain. 185 * 186 * @return 0 if successful, fails otherwise. 187 */ 188 int k_mem_domain_add_thread(struct k_mem_domain *domain, 189 k_tid_t thread); 190 191 #ifdef __cplusplus 192 } 193 #endif 194 195 /** @} */ 196 #endif /* INCLUDE_APP_MEMORY_MEM_DOMAIN_H */ 197