Chunlin Han | e9c9702 | 2017-07-07 20:29:30 +0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2017 Linaro Limited |
| 3 | * |
| 4 | * SPDX-License-Identifier: Apache-2.0 |
| 5 | */ |
| 6 | |
Gerard Marull-Paretas | cffefc8 | 2022-05-06 11:04:23 +0200 | [diff] [blame] | 7 | #include <zephyr/init.h> |
| 8 | #include <zephyr/kernel.h> |
| 9 | #include <zephyr/kernel_structs.h> |
Ramakrishna Pallala | 301acb8 | 2018-01-31 10:11:47 +0530 | [diff] [blame] | 10 | #include <kernel_internal.h> |
Gerard Marull-Paretas | cffefc8 | 2022-05-06 11:04:23 +0200 | [diff] [blame] | 11 | #include <zephyr/sys/__assert.h> |
Flavio Ceolin | 6fdc56d | 2018-09-18 12:32:27 -0700 | [diff] [blame] | 12 | #include <stdbool.h> |
Gerard Marull-Paretas | cffefc8 | 2022-05-06 11:04:23 +0200 | [diff] [blame] | 13 | #include <zephyr/spinlock.h> |
| 14 | #include <zephyr/sys/check.h> |
| 15 | #include <zephyr/sys/libc-hooks.h> |
| 16 | #include <zephyr/logging/log.h> |
Krzysztof Chruscinski | 3ed8083 | 2020-11-26 19:32:34 +0100 | [diff] [blame] | 17 | LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); |
Andrew Boie | bc35b0b | 2020-08-19 13:11:47 -0700 | [diff] [blame] | 18 | |
Andrew Boie | 348a0fd | 2020-10-06 15:53:43 -0700 | [diff] [blame] | 19 | struct k_spinlock z_mem_domain_lock; |
Kumar Gala | a1b77fd | 2020-05-27 11:26:57 -0500 | [diff] [blame] | 20 | static uint8_t max_partitions; |
Chunlin Han | e9c9702 | 2017-07-07 20:29:30 +0800 | [diff] [blame] | 21 | |
Andrew Boie | 9bfc8d8 | 2020-08-25 14:42:33 -0700 | [diff] [blame] | 22 | struct k_mem_domain k_mem_domain_default; |
| 23 | |
Andrew Boie | 72792a5 | 2020-08-19 15:06:37 -0700 | [diff] [blame] | 24 | static bool check_add_partition(struct k_mem_domain *domain, |
| 25 | struct k_mem_partition *part) |
Leandro Pereira | db094b8 | 2018-02-28 14:11:41 -0800 | [diff] [blame] | 26 | { |
Leandro Pereira | b007b64 | 2017-10-17 17:01:48 -0700 | [diff] [blame] | 27 | |
Andrew Boie | 72792a5 | 2020-08-19 15:06:37 -0700 | [diff] [blame] | 28 | int i; |
| 29 | uintptr_t pstart, pend, dstart, dend; |
Leandro Pereira | db094b8 | 2018-02-28 14:11:41 -0800 | [diff] [blame] | 30 | |
Andrew Boie | 72792a5 | 2020-08-19 15:06:37 -0700 | [diff] [blame] | 31 | if (part == NULL) { |
| 32 | LOG_ERR("NULL k_mem_partition provided"); |
Leandro Pereira | db094b8 | 2018-02-28 14:11:41 -0800 | [diff] [blame] | 33 | return false; |
| 34 | } |
| 35 | |
Andrew Boie | 72792a5 | 2020-08-19 15:06:37 -0700 | [diff] [blame] | 36 | #ifdef CONFIG_EXECUTE_XOR_WRITE |
| 37 | /* Arches where execution cannot be disabled should always return |
| 38 | * false to this check |
| 39 | */ |
| 40 | if (K_MEM_PARTITION_IS_EXECUTABLE(part->attr) && |
| 41 | K_MEM_PARTITION_IS_WRITABLE(part->attr)) { |
| 42 | LOG_ERR("partition is writable and executable <start %lx>", |
| 43 | part->start); |
Ioannis Glaropoulos | 6c54cac | 2018-11-13 16:28:55 +0100 | [diff] [blame] | 44 | return false; |
Andrew Boie | 72792a5 | 2020-08-19 15:06:37 -0700 | [diff] [blame] | 45 | } |
Simon Hein | bcd1d19 | 2024-03-08 12:00:10 +0100 | [diff] [blame] | 46 | #endif /* CONFIG_EXECUTE_XOR_WRITE */ |
Leandro Pereira | db094b8 | 2018-02-28 14:11:41 -0800 | [diff] [blame] | 47 | |
Anas Nashif | bbbc38b | 2021-03-29 10:03:49 -0400 | [diff] [blame] | 48 | if (part->size == 0U) { |
Andrew Boie | 72792a5 | 2020-08-19 15:06:37 -0700 | [diff] [blame] | 49 | LOG_ERR("zero sized partition at %p with base 0x%lx", |
| 50 | part, part->start); |
| 51 | return false; |
| 52 | } |
Leandro Pereira | db094b8 | 2018-02-28 14:11:41 -0800 | [diff] [blame] | 53 | |
Andrew Boie | 72792a5 | 2020-08-19 15:06:37 -0700 | [diff] [blame] | 54 | pstart = part->start; |
| 55 | pend = part->start + part->size; |
| 56 | |
| 57 | if (pend <= pstart) { |
| 58 | LOG_ERR("invalid partition %p, wraparound detected. base 0x%lx size %zu", |
| 59 | part, part->start, part->size); |
| 60 | return false; |
| 61 | } |
| 62 | |
| 63 | /* Check that this partition doesn't overlap any existing ones already |
| 64 | * in the domain |
| 65 | */ |
| 66 | for (i = 0; i < domain->num_partitions; i++) { |
| 67 | struct k_mem_partition *dpart = &domain->partitions[i]; |
| 68 | |
Anas Nashif | bbbc38b | 2021-03-29 10:03:49 -0400 | [diff] [blame] | 69 | if (dpart->size == 0U) { |
Andrew Boie | 72792a5 | 2020-08-19 15:06:37 -0700 | [diff] [blame] | 70 | /* Unused slot */ |
| 71 | continue; |
| 72 | } |
| 73 | |
| 74 | dstart = dpart->start; |
| 75 | dend = dstart + dpart->size; |
| 76 | |
| 77 | if (pend > dstart && dend > pstart) { |
| 78 | LOG_ERR("partition %p base %lx (size %zu) overlaps existing base %lx (size %zu)", |
| 79 | part, part->start, part->size, |
| 80 | dpart->start, dpart->size); |
Leandro Pereira | db094b8 | 2018-02-28 14:11:41 -0800 | [diff] [blame] | 81 | return false; |
| 82 | } |
| 83 | } |
| 84 | |
| 85 | return true; |
Leandro Pereira | b007b64 | 2017-10-17 17:01:48 -0700 | [diff] [blame] | 86 | } |
Leandro Pereira | db094b8 | 2018-02-28 14:11:41 -0800 | [diff] [blame] | 87 | |
Daniel Leung | fb91ce2 | 2021-11-11 12:49:58 -0800 | [diff] [blame] | 88 | int k_mem_domain_init(struct k_mem_domain *domain, uint8_t num_parts, |
| 89 | struct k_mem_partition *parts[]) |
Chunlin Han | e9c9702 | 2017-07-07 20:29:30 +0800 | [diff] [blame] | 90 | { |
Andy Ross | 04382b9 | 2018-07-24 11:35:55 -0700 | [diff] [blame] | 91 | k_spinlock_key_t key; |
Daniel Leung | fb91ce2 | 2021-11-11 12:49:58 -0800 | [diff] [blame] | 92 | int ret = 0; |
Chunlin Han | e9c9702 | 2017-07-07 20:29:30 +0800 | [diff] [blame] | 93 | |
Daniel Leung | fb91ce2 | 2021-11-11 12:49:58 -0800 | [diff] [blame] | 94 | CHECKIF(domain == NULL) { |
| 95 | ret = -EINVAL; |
| 96 | goto out; |
| 97 | } |
| 98 | |
| 99 | CHECKIF(!(num_parts == 0U || parts != NULL)) { |
| 100 | LOG_ERR("parts array is NULL and num_parts is nonzero"); |
| 101 | ret = -EINVAL; |
| 102 | goto out; |
| 103 | } |
| 104 | |
| 105 | CHECKIF(!(num_parts <= max_partitions)) { |
| 106 | LOG_ERR("num_parts of %d exceeds maximum allowable partitions (%d)", |
| 107 | num_parts, max_partitions); |
| 108 | ret = -EINVAL; |
| 109 | goto out; |
| 110 | } |
Chunlin Han | e9c9702 | 2017-07-07 20:29:30 +0800 | [diff] [blame] | 111 | |
Andrew Boie | 348a0fd | 2020-10-06 15:53:43 -0700 | [diff] [blame] | 112 | key = k_spin_lock(&z_mem_domain_lock); |
Chunlin Han | e9c9702 | 2017-07-07 20:29:30 +0800 | [diff] [blame] | 113 | |
Patrik Flykt | 24d7143 | 2019-03-26 19:57:45 -0600 | [diff] [blame] | 114 | domain->num_partitions = 0U; |
Flavio Ceolin | da49f2e | 2018-09-11 19:09:03 -0700 | [diff] [blame] | 115 | (void)memset(domain->partitions, 0, sizeof(domain->partitions)); |
Chunlin Han | e9c9702 | 2017-07-07 20:29:30 +0800 | [diff] [blame] | 116 | sys_dlist_init(&domain->mem_domain_q); |
| 117 | |
Andrew Boie | bc35b0b | 2020-08-19 13:11:47 -0700 | [diff] [blame] | 118 | #ifdef CONFIG_ARCH_MEM_DOMAIN_DATA |
Daniel Leung | fb91ce2 | 2021-11-11 12:49:58 -0800 | [diff] [blame] | 119 | ret = arch_mem_domain_init(domain); |
Andrew Boie | bc35b0b | 2020-08-19 13:11:47 -0700 | [diff] [blame] | 120 | |
Andrew Boie | bc35b0b | 2020-08-19 13:11:47 -0700 | [diff] [blame] | 121 | if (ret != 0) { |
| 122 | LOG_ERR("architecture-specific initialization failed for domain %p with %d", |
| 123 | domain, ret); |
Daniel Leung | fb91ce2 | 2021-11-11 12:49:58 -0800 | [diff] [blame] | 124 | ret = -ENOMEM; |
| 125 | goto unlock_out; |
Andrew Boie | bc35b0b | 2020-08-19 13:11:47 -0700 | [diff] [blame] | 126 | } |
Simon Hein | bcd1d19 | 2024-03-08 12:00:10 +0100 | [diff] [blame] | 127 | #endif /* CONFIG_ARCH_MEM_DOMAIN_DATA */ |
Andrew Boie | 52bf482 | 2020-10-16 16:49:41 -0700 | [diff] [blame] | 128 | if (num_parts != 0U) { |
| 129 | uint32_t i; |
| 130 | |
| 131 | for (i = 0U; i < num_parts; i++) { |
Daniel Leung | fb91ce2 | 2021-11-11 12:49:58 -0800 | [diff] [blame] | 132 | CHECKIF(!check_add_partition(domain, parts[i])) { |
| 133 | LOG_ERR("invalid partition index %d (%p)", |
| 134 | i, parts[i]); |
| 135 | ret = -EINVAL; |
| 136 | goto unlock_out; |
| 137 | } |
Andrew Boie | 52bf482 | 2020-10-16 16:49:41 -0700 | [diff] [blame] | 138 | |
| 139 | domain->partitions[i] = *parts[i]; |
| 140 | domain->num_partitions++; |
| 141 | #ifdef CONFIG_ARCH_MEM_DOMAIN_SYNCHRONOUS_API |
Daniel Leung | a603171 | 2021-11-12 16:10:10 -0800 | [diff] [blame] | 142 | int ret2 = arch_mem_domain_partition_add(domain, i); |
| 143 | |
| 144 | ARG_UNUSED(ret2); |
| 145 | CHECKIF(ret2 != 0) { |
| 146 | ret = ret2; |
| 147 | } |
Simon Hein | bcd1d19 | 2024-03-08 12:00:10 +0100 | [diff] [blame] | 148 | #endif /* CONFIG_ARCH_MEM_DOMAIN_SYNCHRONOUS_API */ |
Andrew Boie | 52bf482 | 2020-10-16 16:49:41 -0700 | [diff] [blame] | 149 | } |
| 150 | } |
Andrew Boie | bc35b0b | 2020-08-19 13:11:47 -0700 | [diff] [blame] | 151 | |
Daniel Leung | fb91ce2 | 2021-11-11 12:49:58 -0800 | [diff] [blame] | 152 | unlock_out: |
Andrew Boie | 348a0fd | 2020-10-06 15:53:43 -0700 | [diff] [blame] | 153 | k_spin_unlock(&z_mem_domain_lock, key); |
Daniel Leung | fb91ce2 | 2021-11-11 12:49:58 -0800 | [diff] [blame] | 154 | |
| 155 | out: |
| 156 | return ret; |
Chunlin Han | e9c9702 | 2017-07-07 20:29:30 +0800 | [diff] [blame] | 157 | } |
| 158 | |
Daniel Leung | bb595a8 | 2021-11-10 11:11:00 -0800 | [diff] [blame] | 159 | int k_mem_domain_add_partition(struct k_mem_domain *domain, |
| 160 | struct k_mem_partition *part) |
Chunlin Han | e9c9702 | 2017-07-07 20:29:30 +0800 | [diff] [blame] | 161 | { |
| 162 | int p_idx; |
Andy Ross | 04382b9 | 2018-07-24 11:35:55 -0700 | [diff] [blame] | 163 | k_spinlock_key_t key; |
Daniel Leung | bb595a8 | 2021-11-10 11:11:00 -0800 | [diff] [blame] | 164 | int ret = 0; |
Chunlin Han | e9c9702 | 2017-07-07 20:29:30 +0800 | [diff] [blame] | 165 | |
Daniel Leung | bb595a8 | 2021-11-10 11:11:00 -0800 | [diff] [blame] | 166 | CHECKIF(domain == NULL) { |
| 167 | ret = -EINVAL; |
| 168 | goto out; |
| 169 | } |
| 170 | |
| 171 | CHECKIF(!check_add_partition(domain, part)) { |
| 172 | LOG_ERR("invalid partition %p", part); |
| 173 | ret = -EINVAL; |
| 174 | goto out; |
| 175 | } |
Leandro Pereira | b007b64 | 2017-10-17 17:01:48 -0700 | [diff] [blame] | 176 | |
Andrew Boie | 348a0fd | 2020-10-06 15:53:43 -0700 | [diff] [blame] | 177 | key = k_spin_lock(&z_mem_domain_lock); |
Chunlin Han | e9c9702 | 2017-07-07 20:29:30 +0800 | [diff] [blame] | 178 | |
| 179 | for (p_idx = 0; p_idx < max_partitions; p_idx++) { |
| 180 | /* A zero-sized partition denotes it's a free partition */ |
Patrik Flykt | 24d7143 | 2019-03-26 19:57:45 -0600 | [diff] [blame] | 181 | if (domain->partitions[p_idx].size == 0U) { |
Chunlin Han | e9c9702 | 2017-07-07 20:29:30 +0800 | [diff] [blame] | 182 | break; |
| 183 | } |
| 184 | } |
| 185 | |
Daniel Leung | bb595a8 | 2021-11-10 11:11:00 -0800 | [diff] [blame] | 186 | CHECKIF(!(p_idx < max_partitions)) { |
| 187 | LOG_ERR("no free partition slots available"); |
| 188 | ret = -ENOSPC; |
| 189 | goto unlock_out; |
| 190 | } |
Chunlin Han | e9c9702 | 2017-07-07 20:29:30 +0800 | [diff] [blame] | 191 | |
Andrew Boie | d11e3c3 | 2020-08-25 16:47:44 -0700 | [diff] [blame] | 192 | LOG_DBG("add partition base %lx size %zu to domain %p\n", |
| 193 | part->start, part->size, domain); |
| 194 | |
Chunlin Han | e9c9702 | 2017-07-07 20:29:30 +0800 | [diff] [blame] | 195 | domain->partitions[p_idx].start = part->start; |
| 196 | domain->partitions[p_idx].size = part->size; |
| 197 | domain->partitions[p_idx].attr = part->attr; |
| 198 | |
| 199 | domain->num_partitions++; |
| 200 | |
Andrew Boie | 00f71b0 | 2020-08-25 17:02:38 -0700 | [diff] [blame] | 201 | #ifdef CONFIG_ARCH_MEM_DOMAIN_SYNCHRONOUS_API |
Daniel Leung | a603171 | 2021-11-12 16:10:10 -0800 | [diff] [blame] | 202 | ret = arch_mem_domain_partition_add(domain, p_idx); |
Simon Hein | bcd1d19 | 2024-03-08 12:00:10 +0100 | [diff] [blame] | 203 | #endif /* CONFIG_ARCH_MEM_DOMAIN_SYNCHRONOUS_API */ |
Daniel Leung | bb595a8 | 2021-11-10 11:11:00 -0800 | [diff] [blame] | 204 | |
| 205 | unlock_out: |
Andrew Boie | 348a0fd | 2020-10-06 15:53:43 -0700 | [diff] [blame] | 206 | k_spin_unlock(&z_mem_domain_lock, key); |
Daniel Leung | bb595a8 | 2021-11-10 11:11:00 -0800 | [diff] [blame] | 207 | |
| 208 | out: |
| 209 | return ret; |
Chunlin Han | e9c9702 | 2017-07-07 20:29:30 +0800 | [diff] [blame] | 210 | } |
| 211 | |
Daniel Leung | bb595a8 | 2021-11-10 11:11:00 -0800 | [diff] [blame] | 212 | int k_mem_domain_remove_partition(struct k_mem_domain *domain, |
Chunlin Han | e9c9702 | 2017-07-07 20:29:30 +0800 | [diff] [blame] | 213 | struct k_mem_partition *part) |
| 214 | { |
| 215 | int p_idx; |
Andy Ross | 04382b9 | 2018-07-24 11:35:55 -0700 | [diff] [blame] | 216 | k_spinlock_key_t key; |
Daniel Leung | bb595a8 | 2021-11-10 11:11:00 -0800 | [diff] [blame] | 217 | int ret = 0; |
Chunlin Han | e9c9702 | 2017-07-07 20:29:30 +0800 | [diff] [blame] | 218 | |
Daniel Leung | bb595a8 | 2021-11-10 11:11:00 -0800 | [diff] [blame] | 219 | CHECKIF((domain == NULL) || (part == NULL)) { |
| 220 | ret = -EINVAL; |
| 221 | goto out; |
| 222 | } |
Chunlin Han | e9c9702 | 2017-07-07 20:29:30 +0800 | [diff] [blame] | 223 | |
Andrew Boie | 348a0fd | 2020-10-06 15:53:43 -0700 | [diff] [blame] | 224 | key = k_spin_lock(&z_mem_domain_lock); |
Chunlin Han | e9c9702 | 2017-07-07 20:29:30 +0800 | [diff] [blame] | 225 | |
| 226 | /* find a partition that matches the given start and size */ |
| 227 | for (p_idx = 0; p_idx < max_partitions; p_idx++) { |
Hess Nathan | 6d417d5 | 2024-04-30 13:26:35 +0200 | [diff] [blame] | 228 | if ((domain->partitions[p_idx].start == part->start) && |
| 229 | (domain->partitions[p_idx].size == part->size)) { |
Chunlin Han | e9c9702 | 2017-07-07 20:29:30 +0800 | [diff] [blame] | 230 | break; |
| 231 | } |
| 232 | } |
| 233 | |
Daniel Leung | bb595a8 | 2021-11-10 11:11:00 -0800 | [diff] [blame] | 234 | CHECKIF(!(p_idx < max_partitions)) { |
| 235 | LOG_ERR("no matching partition found"); |
| 236 | ret = -ENOENT; |
| 237 | goto unlock_out; |
| 238 | } |
Chunlin Han | e9c9702 | 2017-07-07 20:29:30 +0800 | [diff] [blame] | 239 | |
Andrew Boie | d11e3c3 | 2020-08-25 16:47:44 -0700 | [diff] [blame] | 240 | LOG_DBG("remove partition base %lx size %zu from domain %p\n", |
| 241 | part->start, part->size, domain); |
| 242 | |
Andrew Boie | 00f71b0 | 2020-08-25 17:02:38 -0700 | [diff] [blame] | 243 | #ifdef CONFIG_ARCH_MEM_DOMAIN_SYNCHRONOUS_API |
Daniel Leung | a603171 | 2021-11-12 16:10:10 -0800 | [diff] [blame] | 244 | ret = arch_mem_domain_partition_remove(domain, p_idx); |
Simon Hein | bcd1d19 | 2024-03-08 12:00:10 +0100 | [diff] [blame] | 245 | #endif /* CONFIG_ARCH_MEM_DOMAIN_SYNCHRONOUS_API */ |
Adithya Baglody | eff2ec6 | 2017-10-09 11:37:31 +0530 | [diff] [blame] | 246 | |
Ioannis Glaropoulos | ccf813c | 2018-12-03 14:21:54 +0100 | [diff] [blame] | 247 | /* A zero-sized partition denotes it's a free partition */ |
Patrik Flykt | 24d7143 | 2019-03-26 19:57:45 -0600 | [diff] [blame] | 248 | domain->partitions[p_idx].size = 0U; |
Chunlin Han | e9c9702 | 2017-07-07 20:29:30 +0800 | [diff] [blame] | 249 | |
| 250 | domain->num_partitions--; |
| 251 | |
Daniel Leung | bb595a8 | 2021-11-10 11:11:00 -0800 | [diff] [blame] | 252 | unlock_out: |
Andrew Boie | 348a0fd | 2020-10-06 15:53:43 -0700 | [diff] [blame] | 253 | k_spin_unlock(&z_mem_domain_lock, key); |
Daniel Leung | bb595a8 | 2021-11-10 11:11:00 -0800 | [diff] [blame] | 254 | |
| 255 | out: |
| 256 | return ret; |
Chunlin Han | e9c9702 | 2017-07-07 20:29:30 +0800 | [diff] [blame] | 257 | } |
| 258 | |
Daniel Leung | a603171 | 2021-11-12 16:10:10 -0800 | [diff] [blame] | 259 | static int add_thread_locked(struct k_mem_domain *domain, |
| 260 | k_tid_t thread) |
Chunlin Han | e9c9702 | 2017-07-07 20:29:30 +0800 | [diff] [blame] | 261 | { |
Daniel Leung | a603171 | 2021-11-12 16:10:10 -0800 | [diff] [blame] | 262 | int ret = 0; |
| 263 | |
Andrew Boie | 72792a5 | 2020-08-19 15:06:37 -0700 | [diff] [blame] | 264 | __ASSERT_NO_MSG(domain != NULL); |
| 265 | __ASSERT_NO_MSG(thread != NULL); |
Chunlin Han | e9c9702 | 2017-07-07 20:29:30 +0800 | [diff] [blame] | 266 | |
Andrew Boie | d11e3c3 | 2020-08-25 16:47:44 -0700 | [diff] [blame] | 267 | LOG_DBG("add thread %p to domain %p\n", thread, domain); |
Chunlin Han | e9c9702 | 2017-07-07 20:29:30 +0800 | [diff] [blame] | 268 | sys_dlist_append(&domain->mem_domain_q, |
| 269 | &thread->mem_domain_info.mem_domain_q_node); |
| 270 | thread->mem_domain_info.mem_domain = domain; |
| 271 | |
Andrew Boie | 00f71b0 | 2020-08-25 17:02:38 -0700 | [diff] [blame] | 272 | #ifdef CONFIG_ARCH_MEM_DOMAIN_SYNCHRONOUS_API |
Daniel Leung | a603171 | 2021-11-12 16:10:10 -0800 | [diff] [blame] | 273 | ret = arch_mem_domain_thread_add(thread); |
Simon Hein | bcd1d19 | 2024-03-08 12:00:10 +0100 | [diff] [blame] | 274 | #endif /* CONFIG_ARCH_MEM_DOMAIN_SYNCHRONOUS_API */ |
Daniel Leung | a603171 | 2021-11-12 16:10:10 -0800 | [diff] [blame] | 275 | |
| 276 | return ret; |
Andrew Boie | b5a71f7 | 2020-10-06 13:39:29 -0700 | [diff] [blame] | 277 | } |
Adithya Baglody | 9cde20a | 2017-12-06 16:48:28 +0530 | [diff] [blame] | 278 | |
Daniel Leung | a603171 | 2021-11-12 16:10:10 -0800 | [diff] [blame] | 279 | static int remove_thread_locked(struct k_thread *thread) |
Andrew Boie | b5a71f7 | 2020-10-06 13:39:29 -0700 | [diff] [blame] | 280 | { |
Daniel Leung | a603171 | 2021-11-12 16:10:10 -0800 | [diff] [blame] | 281 | int ret = 0; |
| 282 | |
Andrew Boie | b5a71f7 | 2020-10-06 13:39:29 -0700 | [diff] [blame] | 283 | __ASSERT_NO_MSG(thread != NULL); |
| 284 | LOG_DBG("remove thread %p from memory domain %p\n", |
| 285 | thread, thread->mem_domain_info.mem_domain); |
| 286 | sys_dlist_remove(&thread->mem_domain_info.mem_domain_q_node); |
| 287 | |
| 288 | #ifdef CONFIG_ARCH_MEM_DOMAIN_SYNCHRONOUS_API |
Daniel Leung | a603171 | 2021-11-12 16:10:10 -0800 | [diff] [blame] | 289 | ret = arch_mem_domain_thread_remove(thread); |
Simon Hein | bcd1d19 | 2024-03-08 12:00:10 +0100 | [diff] [blame] | 290 | #endif /* CONFIG_ARCH_MEM_DOMAIN_SYNCHRONOUS_API */ |
Daniel Leung | a603171 | 2021-11-12 16:10:10 -0800 | [diff] [blame] | 291 | |
| 292 | return ret; |
Andrew Boie | b5a71f7 | 2020-10-06 13:39:29 -0700 | [diff] [blame] | 293 | } |
| 294 | |
| 295 | /* Called from thread object initialization */ |
| 296 | void z_mem_domain_init_thread(struct k_thread *thread) |
| 297 | { |
Daniel Leung | a603171 | 2021-11-12 16:10:10 -0800 | [diff] [blame] | 298 | int ret; |
Andrew Boie | 348a0fd | 2020-10-06 15:53:43 -0700 | [diff] [blame] | 299 | k_spinlock_key_t key = k_spin_lock(&z_mem_domain_lock); |
Andrew Boie | b5a71f7 | 2020-10-06 13:39:29 -0700 | [diff] [blame] | 300 | |
| 301 | /* New threads inherit memory domain configuration from parent */ |
Daniel Leung | a603171 | 2021-11-12 16:10:10 -0800 | [diff] [blame] | 302 | ret = add_thread_locked(_current->mem_domain_info.mem_domain, thread); |
| 303 | __ASSERT_NO_MSG(ret == 0); |
| 304 | ARG_UNUSED(ret); |
| 305 | |
Andrew Boie | 348a0fd | 2020-10-06 15:53:43 -0700 | [diff] [blame] | 306 | k_spin_unlock(&z_mem_domain_lock, key); |
Andrew Boie | b5a71f7 | 2020-10-06 13:39:29 -0700 | [diff] [blame] | 307 | } |
| 308 | |
Anas Nashif | 0d8da5f | 2024-03-06 15:59:36 -0500 | [diff] [blame] | 309 | /* Called when thread aborts during teardown tasks. _sched_spinlock is held */ |
Andrew Boie | b5a71f7 | 2020-10-06 13:39:29 -0700 | [diff] [blame] | 310 | void z_mem_domain_exit_thread(struct k_thread *thread) |
| 311 | { |
Daniel Leung | a603171 | 2021-11-12 16:10:10 -0800 | [diff] [blame] | 312 | int ret; |
| 313 | |
Andrew Boie | 348a0fd | 2020-10-06 15:53:43 -0700 | [diff] [blame] | 314 | k_spinlock_key_t key = k_spin_lock(&z_mem_domain_lock); |
Daniel Leung | a603171 | 2021-11-12 16:10:10 -0800 | [diff] [blame] | 315 | |
| 316 | ret = remove_thread_locked(thread); |
| 317 | __ASSERT_NO_MSG(ret == 0); |
| 318 | ARG_UNUSED(ret); |
| 319 | |
Andrew Boie | 348a0fd | 2020-10-06 15:53:43 -0700 | [diff] [blame] | 320 | k_spin_unlock(&z_mem_domain_lock, key); |
Andrew Boie | b5a71f7 | 2020-10-06 13:39:29 -0700 | [diff] [blame] | 321 | } |
| 322 | |
Daniel Leung | a603171 | 2021-11-12 16:10:10 -0800 | [diff] [blame] | 323 | int k_mem_domain_add_thread(struct k_mem_domain *domain, k_tid_t thread) |
Andrew Boie | b5a71f7 | 2020-10-06 13:39:29 -0700 | [diff] [blame] | 324 | { |
Daniel Leung | a603171 | 2021-11-12 16:10:10 -0800 | [diff] [blame] | 325 | int ret = 0; |
Andrew Boie | b5a71f7 | 2020-10-06 13:39:29 -0700 | [diff] [blame] | 326 | k_spinlock_key_t key; |
| 327 | |
Andrew Boie | 348a0fd | 2020-10-06 15:53:43 -0700 | [diff] [blame] | 328 | key = k_spin_lock(&z_mem_domain_lock); |
Andrew Boie | fa6db61 | 2020-10-20 13:26:19 -0700 | [diff] [blame] | 329 | if (thread->mem_domain_info.mem_domain != domain) { |
Daniel Leung | a603171 | 2021-11-12 16:10:10 -0800 | [diff] [blame] | 330 | ret = remove_thread_locked(thread); |
| 331 | |
| 332 | if (ret == 0) { |
| 333 | ret = add_thread_locked(domain, thread); |
| 334 | } |
Andrew Boie | fa6db61 | 2020-10-20 13:26:19 -0700 | [diff] [blame] | 335 | } |
Andrew Boie | 348a0fd | 2020-10-06 15:53:43 -0700 | [diff] [blame] | 336 | k_spin_unlock(&z_mem_domain_lock, key); |
Daniel Leung | a603171 | 2021-11-12 16:10:10 -0800 | [diff] [blame] | 337 | |
| 338 | return ret; |
Chunlin Han | e9c9702 | 2017-07-07 20:29:30 +0800 | [diff] [blame] | 339 | } |
| 340 | |
Gerard Marull-Paretas | a5fd0d1 | 2022-10-19 09:33:44 +0200 | [diff] [blame] | 341 | static int init_mem_domain_module(void) |
Chunlin Han | e9c9702 | 2017-07-07 20:29:30 +0800 | [diff] [blame] | 342 | { |
Daniel Leung | fb91ce2 | 2021-11-11 12:49:58 -0800 | [diff] [blame] | 343 | int ret; |
| 344 | |
Daniel Leung | fb91ce2 | 2021-11-11 12:49:58 -0800 | [diff] [blame] | 345 | ARG_UNUSED(ret); |
Chunlin Han | e9c9702 | 2017-07-07 20:29:30 +0800 | [diff] [blame] | 346 | |
Andrew Boie | 4f77c2a | 2019-11-07 12:43:29 -0800 | [diff] [blame] | 347 | max_partitions = arch_mem_domain_max_partitions_get(); |
Chunlin Han | e9c9702 | 2017-07-07 20:29:30 +0800 | [diff] [blame] | 348 | /* |
| 349 | * max_partitions must be less than or equal to |
| 350 | * CONFIG_MAX_DOMAIN_PARTITIONS, or would encounter array index |
| 351 | * out of bounds error. |
| 352 | */ |
| 353 | __ASSERT(max_partitions <= CONFIG_MAX_DOMAIN_PARTITIONS, ""); |
| 354 | |
Daniel Leung | fb91ce2 | 2021-11-11 12:49:58 -0800 | [diff] [blame] | 355 | ret = k_mem_domain_init(&k_mem_domain_default, 0, NULL); |
| 356 | __ASSERT(ret == 0, "failed to init default mem domain"); |
| 357 | |
Andrew Boie | 9bfc8d8 | 2020-08-25 14:42:33 -0700 | [diff] [blame] | 358 | #ifdef Z_LIBC_PARTITION_EXISTS |
Daniel Leung | bb595a8 | 2021-11-10 11:11:00 -0800 | [diff] [blame] | 359 | ret = k_mem_domain_add_partition(&k_mem_domain_default, |
| 360 | &z_libc_partition); |
| 361 | __ASSERT(ret == 0, "failed to add default libc mem partition"); |
Andrew Boie | 9bfc8d8 | 2020-08-25 14:42:33 -0700 | [diff] [blame] | 362 | #endif /* Z_LIBC_PARTITION_EXISTS */ |
| 363 | |
Chunlin Han | e9c9702 | 2017-07-07 20:29:30 +0800 | [diff] [blame] | 364 | return 0; |
| 365 | } |
| 366 | |
| 367 | SYS_INIT(init_mem_domain_module, PRE_KERNEL_1, |
| 368 | CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); |