178 lines
5.3 KiB
ReStructuredText
178 lines
5.3 KiB
ReStructuredText
.. _memory_domain:
|
|
|
|
Memory Domain
|
|
#############
|
|
|
|
The memory domain APIs are used by unprivileged threads to share data to
|
|
the threads in the same memory domain and protect sensitive data from threads
|
|
outside their domain. Memory domains are not only used for improving security,
|
|
but are also useful for debugging (unexpected access would cause exception).
|
|
|
|
.. contents::
|
|
:local:
|
|
:depth: 2
|
|
|
|
Concepts
|
|
********
|
|
|
|
A memory domain contains some number of memory partitions.
|
|
A memory partition is a memory region (might be RAM, peripheral registers,
|
|
or flash, for example) with specific attributes (access permission, e.g.
|
|
privileged read/write, unprivileged read-only, or execute never).
|
|
Memory partitions are defined by a set of underlying MPU regions
|
|
or MMU tables. A thread belongs to a single memory domain at
|
|
any point in time but a memory domain may contain multiple threads.
|
|
Threads in the same memory domain have the same access permissions
|
|
to the memory partitions belong to the memory domain.
|
|
|
|
Implementation
|
|
**************
|
|
|
|
Create a Memory Domain
|
|
======================
|
|
|
|
A memory domain is defined using a variable of type
|
|
:c:type:`struct k_mem_domain`. It must then be initialized by calling
|
|
:cpp:func:`k_mem_domain_init()`.
|
|
|
|
The following code defines and initializes an empty memory domain.
|
|
|
|
.. code-block:: c
|
|
|
|
struct k_mem_domain app0_domain;
|
|
|
|
k_mem_domain_init(&app0_domain, "app0_domain", 0, NULL);
|
|
|
|
Add Memory Partitions into a Memory Domain
|
|
==========================================
|
|
|
|
There are two ways to add memory partitions into a memory domain.
|
|
|
|
This first code sample shows how to add memory partitions while creating
|
|
a memory domain.
|
|
|
|
.. code-block:: c
|
|
|
|
/* the start address of the MPU region needs to align with its size */
|
|
u8_t __aligned(32) app0_buf[32];
|
|
u8_t __aligned(32) app1_buf[32];
|
|
|
|
K_MEM_PARTITION_DEFINE(app0_part0, app0_buf, sizeof(app0_buf),
|
|
K_MEM_PARTITION_P_RW_U_RW);
|
|
|
|
K_MEM_PARTITION_DEFINE(app0_part1, app1_buf, sizeof(app1_buf),
|
|
K_MEM_PARTITION_P_RW_U_RO);
|
|
|
|
struct k_mem_partition *app0_parts[] = {
|
|
app0_part0,
|
|
app0_part1
|
|
};
|
|
|
|
k_mem_domain_init(&app0_domain, ARRAY_SIZE(app0_parts), app0_parts);
|
|
|
|
This second code sample shows how to add memory partitions into an initialized
|
|
memory domain one by one.
|
|
|
|
.. code-block:: c
|
|
|
|
/* the start address of the MPU region needs to align with its size */
|
|
u8_t __aligned(32) app0_buf[32];
|
|
u8_t __aligned(32) app1_buf[32];
|
|
|
|
K_MEM_PARTITION_DEFINE(app0_part0, app0_buf, sizeof(app0_buf),
|
|
K_MEM_PARTITION_P_RW_U_RW);
|
|
|
|
K_MEM_PARTITION_DEFINE(app0_part1, app1_buf, sizeof(app1_buf),
|
|
K_MEM_PARTITION_P_RW_U_RO);
|
|
|
|
k_mem_domain_add_partition(&app0_domain, &app0_part0);
|
|
k_mem_domain_add_partition(&app0_domain, &app0_part1);
|
|
|
|
.. note::
|
|
The maximum number of memory partitions is limited by the maximum
|
|
number of MPU regions or the maximum number of MMU tables.
|
|
|
|
Add Threads into a Memory Domain
|
|
================================
|
|
|
|
Adding threads into a memory domain grants threads permission to access
|
|
the memory partitions in the memory domain.
|
|
|
|
The following code shows how to add threads into a memory domain.
|
|
|
|
.. code-block:: c
|
|
|
|
k_mem_domain_add_thread(&app0_domain, &app_thread_id);
|
|
|
|
Remove a Memory Partition from a Memory Domain
|
|
==============================================
|
|
|
|
The following code shows how to remove a memory partition from a memory
|
|
domain.
|
|
|
|
.. code-block:: c
|
|
|
|
k_mem_domain_remove_partition(&app0_domain, &app0_part1);
|
|
|
|
The k_mem_domain_remove_partition() API finds the memory partition
|
|
that matches the given parameter and removes that partition from the
|
|
memory domain.
|
|
|
|
Remove a Thread from the Memory Domain
|
|
======================================
|
|
|
|
The following code shows how to remove a thread from the memory domain.
|
|
|
|
.. code-block:: c
|
|
|
|
k_mem_domain_remove_thread(&app0_domain, &app_thread_id);
|
|
|
|
Destroy a Memory Domain
|
|
=======================
|
|
|
|
The following code shows how to destroy a memory domain.
|
|
|
|
.. code-block:: c
|
|
|
|
k_mem_domain_destroy(&app0_domain);
|
|
|
|
Available Partition Attributes
|
|
==============================
|
|
|
|
When defining a partition, we need to set access permission attributes
|
|
to the partition. Since the access control of memory partitions relies on
|
|
either an MPU or MMU, the available partition attributes would be architecture
|
|
dependent.
|
|
|
|
The complete list of available partition attributes for a specific architecture
|
|
is found in the architecture-specific include file
|
|
``include/arch/<arch name>/arch.h``, (for example, ``include/arch/arm/arch.h``.)
|
|
Some examples of partition attributes are:
|
|
|
|
.. code-block:: c
|
|
|
|
/* Denote partition is privileged read/write, unprivileged read/write */
|
|
K_MEM_PARTITION_P_RW_U_RW
|
|
/* Denote partition is privileged read/write, unprivileged read-only */
|
|
K_MEM_PARTITION_P_RW_U_RO
|
|
|
|
Configuration Options
|
|
*********************
|
|
|
|
Related configuration options:
|
|
|
|
* :option:`CONFIG_MAX_DOMAIN_PARTITIONS`
|
|
|
|
APIs
|
|
****
|
|
|
|
The following memory domain APIs are provided by :file:`kernel.h`:
|
|
|
|
* :c:macro:`K_MEM_PARTITION_DEFINE`
|
|
* :cpp:func:`k_mem_domain_init()`
|
|
* :cpp:func:`k_mem_domain_destroy()`
|
|
* :cpp:func:`k_mem_domain_add_partition()`
|
|
* :cpp:func:`k_mem_domain_remove_partition()`
|
|
* :cpp:func:`k_mem_domain_add_thread()`
|
|
* :cpp:func:`k_mem_domain_remove_thread()`
|