Line data Source code
1 0 : /*
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 ZEPHYR_INCLUDE_APP_MEMORY_MEM_DOMAIN_H_
9 : #define ZEPHYR_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 1 : #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 1 : struct k_mem_partition {
56 : /** start address of memory partition */
57 1 : uintptr_t start;
58 : /** size of memory partition */
59 1 : size_t size;
60 : /** attribute of memory partition */
61 1 : 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 1 : 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 1 : struct k_mem_partition partitions[CONFIG_MAX_DOMAIN_PARTITIONS];
86 : /** Doubly linked list of member threads */
87 1 : sys_dlist_t mem_domain_q;
88 : /** number of active partitions in the domain */
89 1 : uint8_t num_partitions;
90 : };
91 :
92 0 : typedef struct k_mem_domain k_mem_domain_t;
93 :
94 : /**
95 : * Default memory domain
96 : *
97 : * All threads are a member of some memory domain, even if running in
98 : * supervisor mode. Threads belong to this default memory domain if they
99 : * haven't been added to or inherited membership from some other domain.
100 : *
101 : * This memory domain has the z_libc_partition partition for the C library
102 : * added to it if exists.
103 : */
104 1 : extern struct k_mem_domain k_mem_domain_default;
105 : #else
106 : /* To support use of IS_ENABLED for the APIs below */
107 : struct k_mem_domain;
108 : struct k_mem_partition;
109 : #endif /* CONFIG_USERSPACE */
110 :
111 : /**
112 : * @brief Initialize a memory domain.
113 : *
114 : * Initialize a memory domain with given name and memory partitions.
115 : *
116 : * See documentation for k_mem_domain_add_partition() for details about
117 : * partition constraints.
118 : *
119 : * Do not call k_mem_domain_init() on the same memory domain more than once,
120 : * doing so is undefined behavior.
121 : *
122 : * @param domain The memory domain to be initialized.
123 : * @param num_parts The number of array items of "parts" parameter.
124 : * @param parts An array of pointers to the memory partitions. Can be NULL
125 : * if num_parts is zero.
126 : *
127 : * @retval 0 if successful
128 : * @retval -EINVAL if invalid parameters supplied
129 : * @retval -ENOMEM if insufficient memory
130 : */
131 1 : int k_mem_domain_init(struct k_mem_domain *domain, uint8_t num_parts,
132 : struct k_mem_partition *parts[]);
133 :
134 : /**
135 : * @brief Add a memory partition into a memory domain.
136 : *
137 : * Add a memory partition into a memory domain. Partitions must conform to
138 : * the following constraints:
139 : *
140 : * - Partitions in the same memory domain may not overlap each other.
141 : * - Partitions must not be defined which expose private kernel
142 : * data structures or kernel objects.
143 : * - The starting address alignment, and the partition size must conform to
144 : * the constraints of the underlying memory management hardware, which
145 : * varies per architecture.
146 : * - Memory domain partitions are only intended to control access to memory
147 : * from user mode threads.
148 : * - If CONFIG_EXECUTE_XOR_WRITE is enabled, the partition must not allow
149 : * both writes and execution.
150 : *
151 : * Violating these constraints may lead to CPU exceptions or undefined
152 : * behavior.
153 : *
154 : * @param domain The memory domain to be added a memory partition.
155 : * @param part The memory partition to be added
156 : *
157 : * @retval 0 if successful
158 : * @retval -EINVAL if invalid parameters supplied
159 : * @retval -ENOSPC if no free partition slots available
160 : */
161 1 : int k_mem_domain_add_partition(struct k_mem_domain *domain,
162 : struct k_mem_partition *part);
163 :
164 : /**
165 : * @brief Remove a memory partition from a memory domain.
166 : *
167 : * Remove a memory partition from a memory domain.
168 : *
169 : * @param domain The memory domain to be removed a memory partition.
170 : * @param part The memory partition to be removed
171 : *
172 : * @retval 0 if successful
173 : * @retval -EINVAL if invalid parameters supplied
174 : * @retval -ENOENT if no matching partition found
175 : */
176 1 : int k_mem_domain_remove_partition(struct k_mem_domain *domain,
177 : struct k_mem_partition *part);
178 :
179 : /**
180 : * @brief Add a thread into a memory domain.
181 : *
182 : * Add a thread into a memory domain. It will be removed from whatever
183 : * memory domain it previously belonged to.
184 : *
185 : * @param domain The memory domain that the thread is going to be added into.
186 : * @param thread ID of thread going to be added into the memory domain.
187 : *
188 : * @return 0 if successful, fails otherwise.
189 : */
190 1 : int k_mem_domain_add_thread(struct k_mem_domain *domain,
191 : k_tid_t thread);
192 :
193 : #ifdef __cplusplus
194 : }
195 : #endif
196 :
197 : /** @} */
198 : #endif /* ZEPHYR_INCLUDE_APP_MEMORY_MEM_DOMAIN_H_ */
|