-
Notifications
You must be signed in to change notification settings - Fork 6.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
mem_attr: Introduce library to query memory attributes
The introduction on the `zephyr,memory-attr` property for memory nodes has been very useful to mark attributes and capabilities of the memory regions defined into the DT. What's still missing is an abstracted and unified way to deal and manage this kind of information. In this PR we introduce a small and extensible library / subsystem that can be used by application, drivers or other subsystems to query this kind of information. One very common use-case of this library is for example to check whether a buffer has certain kind of capabilities (i.e. it is cacheable / non-cacheable). Signed-off-by: Carlo Caione <[email protected]>
- Loading branch information
1 parent
ab59087
commit 7f4e287
Showing
13 changed files
with
284 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
.. _mem_mgmt_api: | ||
|
||
Memory Attributes management API | ||
================================ | ||
|
||
API Reference | ||
************* | ||
|
||
.. doxygengroup:: memory_attr_interface |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
/* | ||
* Copyright (c) 2023 Carlo Caione <[email protected]> | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#ifndef ZEPHYR_INCLUDE_MEM_ATTR_H_ | ||
#define ZEPHYR_INCLUDE_MEM_ATTR_H_ | ||
|
||
/** | ||
* @brief Memory-Attr Interface | ||
* @defgroup memory_attr_interface Memory-Attr Interface | ||
* @ingroup mem_mgmt | ||
* @{ | ||
*/ | ||
|
||
#include <stddef.h> | ||
#include <zephyr/types.h> | ||
#include <zephyr/dt-bindings/memory-attr/memory-attr.h> | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
/** | ||
* @brief memory-attr region structure. | ||
* | ||
* This structure represents the data gathered from DT about a memory-region | ||
* marked with memory attribute. | ||
*/ | ||
struct mem_attr_region_t { | ||
/** Memory region physical address */ | ||
uintptr_t dt_addr; | ||
/** Memory region size */ | ||
size_t dt_size; | ||
/** Memory region attribute */ | ||
enum dt_memory_attr dt_attr; | ||
}; | ||
|
||
/** | ||
* @brief Get the list of memory regions. | ||
* | ||
* Get the list of enabled memory regions with their memory-attribute as | ||
* gathered by DT. | ||
* | ||
* @retval a const struct pointer to the memory regions array. | ||
* @retval NULL if there are no regions. | ||
*/ | ||
const struct mem_attr_region_t *mem_attr_get_regions(void); | ||
|
||
/** | ||
* @brief Check if a buffer has correct size and attributes. | ||
* | ||
* This function is used to check if a given buffer with a given attribute | ||
* fully match a memory regions in terms of size and attributes. This is | ||
* usually used to verify that a buffer has the expected attributes (for | ||
* example the buffer is cacheable / non-cacheable or belongs to RAM / FLASH, | ||
* etc...). | ||
* | ||
* @param addr Virtual address of the user buffer. | ||
* @param size Size of the user buffer. | ||
* @param attr Expected / desired attribute for the buffer. | ||
* | ||
* @retval 0 if the buffer has the correct size and attribute. | ||
* @retval -ENOSYS if the operation is not supported (for example if the MMU is enabled). | ||
* @retval -ENOTSUP if the wrong parameters were passed. | ||
* @retval -EINVAL if the buffer has the wrong attribute. | ||
* @retval -ENOSPC if the buffer is too big for the region it belongs to. | ||
* @retval -ENOBUFS if the buffer is allocated outside a memory region. | ||
*/ | ||
int mem_attr_check_buf(void *addr, size_t size, enum dt_memory_attr attr); | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
/** @} */ | ||
|
||
#endif /* ZEPHYR_INCLUDE_MEM_ATTR_H_ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
zephyr_sources_ifdef(CONFIG_MEM_ATTR mem_attr.c) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# Copyright (c) 2023 Carlo Caione <[email protected]> | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
config MEM_ATTR | ||
bool "Memory Attributes management library" | ||
help | ||
Enable a small library to manage the memory regions defined in the DT | ||
with a `zephyr,memory-attr` property. This library builds at build | ||
time an array of the memory regions defined in the DT that can be | ||
probed at run-time using several helper functions. Set to `N` if | ||
unsure to save RODATA space. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
/* | ||
* Copyright (c) 2023 Carlo Caione, <[email protected]> | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <zephyr/kernel.h> | ||
#include <zephyr/mem_mgmt/mem_attr.h> | ||
|
||
#define _BUILD_MEM_ATTR_REGION(node_id) \ | ||
{ \ | ||
.dt_addr = DT_REG_ADDR(node_id), \ | ||
.dt_size = DT_REG_SIZE(node_id), \ | ||
.dt_attr = DT_ENUM_IDX(node_id, zephyr_memory_attr), \ | ||
}, | ||
|
||
static const struct mem_attr_region_t mem_attr_region[] = { | ||
DT_MEMORY_ATTR_FOREACH_STATUS_OKAY_NODE(_BUILD_MEM_ATTR_REGION) | ||
}; | ||
|
||
const struct mem_attr_region_t *mem_attr_get_regions(void) | ||
{ | ||
if (ARRAY_SIZE(mem_attr_region) == 0) { | ||
return NULL; | ||
} | ||
|
||
return mem_attr_region; | ||
} | ||
|
||
int mem_attr_check_buf(void *v_addr, size_t size, enum dt_memory_attr attr) | ||
{ | ||
uintptr_t addr = (uintptr_t) v_addr; | ||
|
||
/* | ||
* If MMU is enabled the address of the buffer is a virtual address | ||
* while the addresses in the DT are physical addresses. Given that we | ||
* have no way of knowing whether a mapping exists, we simply bail out. | ||
*/ | ||
if (IS_ENABLED(CONFIG_MMU)) { | ||
return -ENOSYS; | ||
} | ||
|
||
if (v_addr == NULL || size == 0 || attr >= DT_MEMORY_ATTR_UNKNOWN) { | ||
return -ENOTSUP; | ||
} | ||
|
||
for (size_t idx = 0; idx < ARRAY_SIZE(mem_attr_region); idx++) { | ||
const struct mem_attr_region_t *region = &mem_attr_region[idx]; | ||
size_t region_end = region->dt_addr + region->dt_size; | ||
|
||
/* Check if the buffer is in the region */ | ||
if ((addr >= region->dt_addr) && (addr < region_end)) { | ||
/* Check if the buffer is entirely contained in the region */ | ||
if ((addr + size) <= region_end) { | ||
/* check if the attribute is correct */ | ||
return (region->dt_attr == attr) ? 0 : -EINVAL; | ||
} | ||
return -ENOSPC; | ||
} | ||
} | ||
return -ENOBUFS; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#SPDX-License-Identifier: Apache-2.0 | ||
|
||
cmake_minimum_required(VERSION 3.20.0) | ||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) | ||
project(test_mem_attr) | ||
|
||
FILE(GLOB app_sources src/*.c) | ||
target_sources(app PRIVATE ${app_sources}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/* | ||
* Copyright (c) 2023 Carlo Caione <[email protected]> | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
/ { | ||
mem_ram: memory@10000000 { | ||
compatible = "vnd,memory-attr"; | ||
reg = <0x10000000 0x1000>; | ||
zephyr,memory-attr = "RAM"; | ||
}; | ||
|
||
mem_ram_nocache: memory@20000000 { | ||
compatible = "vnd,memory-attr"; | ||
reg = <0x20000000 0x2000>; | ||
zephyr,memory-attr = "RAM_NOCACHE"; | ||
}; | ||
|
||
mem_ram_disabled: memory@30000000 { | ||
compatible = "vnd,memory-attr"; | ||
reg = <0x30000000 0x3000>; | ||
zephyr,memory-attr = "FLASH"; | ||
status = "disabled"; | ||
}; | ||
|
||
}; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
CONFIG_ZTEST=y | ||
CONFIG_ZTEST_NEW_API=y | ||
CONFIG_MEM_ATTR=y |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
/* | ||
* Copyright (c) 2023 Carlo Caione <[email protected]> | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <zephyr/ztest.h> | ||
#include <zephyr/mem_mgmt/mem_attr.h> | ||
|
||
ZTEST(mem_attr, test_mem_attr) | ||
{ | ||
const struct mem_attr_region_t *region; | ||
|
||
region = mem_attr_get_regions(); | ||
zassert_true(region != NULL, "No regions returned"); | ||
|
||
/* | ||
* Check the data in the regions | ||
*/ | ||
zassert_equal(region[0].dt_addr, 0x10000000, "Wrong region address"); | ||
zassert_equal(region[0].dt_size, 0x1000, "Wrong region size"); | ||
zassert_equal(region[0].dt_attr, DT_MEMORY_ATTR_RAM, "Wrong region address"); | ||
|
||
zassert_equal(region[1].dt_addr, 0x20000000, "Wrong region address"); | ||
zassert_equal(region[1].dt_size, 0x2000, "Wrong region size"); | ||
zassert_equal(region[1].dt_attr, DT_MEMORY_ATTR_RAM_NOCACHE, "Wrong region address"); | ||
|
||
/* | ||
* Check the input sanitization | ||
*/ | ||
zassert_equal(mem_attr_check_buf((void *) 0x0, 0x1000, DT_MEMORY_ATTR_RAM), | ||
-ENOTSUP, "Unexpected return value"); | ||
zassert_equal(mem_attr_check_buf((void *) 0x10000000, 0x0, DT_MEMORY_ATTR_RAM), | ||
-ENOTSUP, "Unexpected return value"); | ||
zassert_equal(mem_attr_check_buf((void *) 0x10000000, 0x100, DT_MEMORY_ATTR_UNKNOWN + 1), | ||
-ENOTSUP, "Unexpected return value"); | ||
|
||
/* | ||
* Check a buffer with the correct properties | ||
*/ | ||
zassert_equal(mem_attr_check_buf((void *) 0x10000100, 0x100, DT_MEMORY_ATTR_RAM), | ||
0, "Unexpected return value"); | ||
zassert_equal(mem_attr_check_buf((void *) 0x20000000, 0x2000, DT_MEMORY_ATTR_RAM_NOCACHE), | ||
0, "Unexpected return value"); | ||
|
||
/* | ||
* Check a buffer with the wrong attribute | ||
*/ | ||
zassert_equal(mem_attr_check_buf((void *) 0x20000000, 0x2000, DT_MEMORY_ATTR_RAM), | ||
-EINVAL, "Unexpected return value"); | ||
|
||
/* | ||
* Check a buffer outsize the regions | ||
*/ | ||
zassert_equal(mem_attr_check_buf((void *) 0x40000000, 0x1000, DT_MEMORY_ATTR_RAM), | ||
-ENOBUFS, "Unexpected return value"); | ||
|
||
/* | ||
* Check a buffer too big for the region | ||
*/ | ||
zassert_equal(mem_attr_check_buf((void *) 0x10000000, 0x2000, DT_MEMORY_ATTR_RAM), | ||
-ENOSPC, "Unexpected return value"); | ||
|
||
/* | ||
* Check a buffer in a disabled region | ||
*/ | ||
zassert_equal(mem_attr_check_buf((void *) 0x30000000, 0x1000, DT_MEMORY_ATTR_FLASH), | ||
-ENOBUFS, "Unexpected return value"); | ||
} | ||
|
||
ZTEST_SUITE(mem_attr, NULL, NULL, NULL, NULL, NULL); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
common: | ||
platform_allow: | ||
- native_posix | ||
- native_posix_64 | ||
integration_platforms: | ||
- native_posix | ||
tests: | ||
mem_mgmt.mem_attr.default: {} |