app_shmem: auto-initialize partitions

There are no longer per-partition initialization functions.
Instead, we iterate over all of them at boot to set up the
derived k_mem_partitions properly.

Some ARC-specific hacks that should never have been applied
have been removed from the userspace test.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
Andrew Boie 2019-01-29 12:56:02 -08:00 committed by Anas Nashif
commit c253a686bf
8 changed files with 53 additions and 157 deletions

View file

@ -42,13 +42,9 @@ The resulting section name can be seen in the linker.map as
"data_smem_id" and "data_smem_idb". "data_smem_id" and "data_smem_idb".
To create a k_mem_partition, call the macro K_APPMEM_PARTITION_DEFINE(part0) To create a k_mem_partition, call the macro K_APPMEM_PARTITION_DEFINE(part0)
where "part0" is the name then used to refer to that partition. where "part0" is the name then used to refer to that partition. The
This macro only creates a function and necessary data structures for standard memory domain APIs may be used to add it to domains; the declared
the later "initialization". name is a k_mem_partition symbol.
Once the partition is initialized, the standard memory domain APIs may
be used to add it to domains; the declared name is a k_mem_partition
symbol.
Example: Example:
@ -64,8 +60,6 @@ Example:
int main() int main()
{ {
appmem_init_part_part0();
appmem_init_app_memory();
k_mem_domain_init(&dom0, 0, NULL) k_mem_domain_init(&dom0, 0, NULL)
k_mem_domain_add_partition(&dom0, part0); k_mem_domain_add_partition(&dom0, part0);
k_mem_domain_add_thread(&dom0, k_current_get()); k_mem_domain_add_thread(&dom0, k_current_get());
@ -80,10 +74,3 @@ app_macro_support.h:
FOR_EACH(K_APPMEM_PARTITION_DEFINE, part0, part1, part2); FOR_EACH(K_APPMEM_PARTITION_DEFINE, part0, part1, part2);
Similarly, the appmem_init_part_* can also be used in the macro:
.. code-block:: c
FOR_EACH(appmem_init_part, part0, part1, part2);

View file

@ -66,10 +66,7 @@ struct app_region {
char *dmem_start; char *dmem_start;
char *bmem_start; char *bmem_start;
u32_t smem_size; u32_t smem_size;
u32_t dmem_size;
u32_t bmem_size;
struct k_mem_partition *partition; struct k_mem_partition *partition;
sys_dnode_t lnode;
}; };
/* /*
@ -81,10 +78,10 @@ struct app_region {
* calculate the region sizes. * calculate the region sizes.
*/ */
#define smem_size_declare(name) extern char data_smem_##name##_size[] #define smem_size_declare(name) extern char data_smem_##name##_size[]
#define smem_size_assign(name) name##_region.smem_size = (u32_t)&data_smem_##name##_size #define smem_size_val(name) ((u32_t)&data_smem_##name##_size)
#else #else
#define smem_size_declare(name) #define smem_size_declare(name)
#define smem_size_assign(name) #define smem_size_val(name) 0
#endif /* CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT */ #endif /* CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT */
/** /**
@ -105,34 +102,16 @@ struct app_region {
smem_size_declare(name); \ smem_size_declare(name); \
_app_dmem_pad(name) char name##_dmem_pad; \ _app_dmem_pad(name) char name##_dmem_pad; \
_app_bmem_pad(name) char name##_bmem_pad; \ _app_bmem_pad(name) char name##_bmem_pad; \
__kernel struct k_mem_partition name; \ struct k_mem_partition name = { \
__kernel struct app_region name##_region; \ .start = (u32_t) &data_smem_##name, \
static inline void appmem_init_part_##name(void) \ .attr = K_MEM_PARTITION_P_RW_U_RW \
{ \ }; \
name##_region.dmem_start = (char *)&data_smem_##name; \ _GENERIC_SECTION(.app_regions.name) \
name##_region.bmem_start = (char *)&data_smem_##name##b; \ struct app_region name##_region = { \
smem_size_assign(name); \ .dmem_start = (char *)&data_smem_##name, \
sys_dlist_append(&app_mem_list, &name##_region.lnode); \ .bmem_start = (char *)&data_smem_##name##b, \
name.start = (u32_t) name##_region.dmem_start; \ .smem_size = smem_size_val(name), \
name.attr = K_MEM_PARTITION_P_RW_U_RW; \ .partition = &name \
name##_region.partition = &name; \ };
}
/*
* The following allows the FOR_EACH macro to call each partition's
* appmem_init_part_##name . Note: semicolon needed or else compiler
* complains as semicolon needed for function call once expanded by
* macro.
*/
#define appmem_init_part(name) \
appmem_init_part_##name();
extern sys_dlist_t app_mem_list;
extern void app_bss_zero(void);
extern void app_calc_size(void);
extern void appmem_init_app_memory(void);
#endif /* ZEPHYR_INCLUDE_APP_MEMORY_APP_MEMDOMAIN_H_ */ #endif /* ZEPHYR_INCLUDE_APP_MEMORY_APP_MEMDOMAIN_H_ */

View file

@ -42,6 +42,13 @@
} }
#endif #endif
SECTION_PROLOGUE(app_shmem_regions, (OPTIONAL),)
{
__app_shmem_regions_start = .;
KEEP(*(SORT(".app_regions.*")));
__app_shmem_regions_end = .;
} GROUP_LINK_IN(ROMABLE_REGION)
SECTION_PROLOGUE (devconfig, (OPTIONAL),) SECTION_PROLOGUE (devconfig, (OPTIONAL),)
{ {
__devconfig_start = .; __devconfig_start = .;

View file

@ -116,7 +116,7 @@
#define APP_INPUT_SECTION(sect) *(MAYBE_EXCLUDE_SOME_FILES sect) #define APP_INPUT_SECTION(sect) *(MAYBE_EXCLUDE_SOME_FILES sect)
#define KERNEL_INPUT_SECTION(sect) *(sect) #define KERNEL_INPUT_SECTION(sect) *(sect)
#define APP_SMEM_SECTION() KEEP(*(SORT(data_smem_[_a-zA-Z0-9]*))) #define APP_SMEM_SECTION() KEEP(*(SORT("data_smem_*")))
#ifdef CONFIG_X86 /* LINKER FILES: defines used by linker script */ #ifdef CONFIG_X86 /* LINKER FILES: defines used by linker script */
/* Should be moved to linker-common-defs.h */ /* Should be moved to linker-common-defs.h */

View file

@ -105,12 +105,7 @@ void main(void)
k_tid_t tPT, tENC, tCT; k_tid_t tPT, tENC, tCT;
k_thread_access_grant(k_current_get(), &allforone); k_thread_access_grant(k_current_get(), &allforone);
/* initialize the partition structures */
FOR_EACH(appmem_init_part, part0, part1, part2, part3, part4);
printk("init partitions complete\n");
appmem_init_app_memory();
printk("init app memory complete\n");
/* /*
* create an enc thread init the memory domain and add partitions * create an enc thread init the memory domain and add partitions
* then add the thread to the domain. * then add the thread to the domain.

View file

@ -679,7 +679,7 @@ class SizeCalculator:
"_k_memory_pool", "exceptions", "initshell", "_k_memory_pool", "exceptions", "initshell",
"_static_thread_area", "_k_timer_area", "_static_thread_area", "_k_timer_area",
"_k_mem_slab_area", "_k_mem_pool_area", "sw_isr_table", "_k_mem_slab_area", "_k_mem_pool_area", "sw_isr_table",
"_k_sem_area", "_k_mutex_area", "_k_sem_area", "_k_mutex_area", "app_shmem_regions",
"_k_fifo_area", "_k_lifo_area", "_k_stack_area", "_k_fifo_area", "_k_lifo_area", "_k_stack_area",
"_k_msgq_area", "_k_mbox_area", "_k_pipe_area", "_k_msgq_area", "_k_mbox_area", "_k_pipe_area",
"net_if", "net_if_dev", "net_stack", "net_l2_data", "net_if", "net_if_dev", "net_stack", "net_l2_data",

View file

@ -1,97 +1,43 @@
#include <zephyr.h>
#include <init.h>
#include <app_memory/app_memdomain.h> #include <app_memory/app_memdomain.h>
#include <misc/dlist.h>
#include <stdarg.h>
#include <string.h> #include <string.h>
#include <misc/__assert.h>
/* extern char __app_shmem_regions_start[];
* Initializes a double linked-list for the calculation of extern char __app_shmem_regions_end[];
* memory subsections.
*/
sys_dlist_t app_mem_list = SYS_DLIST_STATIC_INIT(&app_mem_list);
/* static int app_shmem_setup(struct device *unused)
* The following zeroizes each "bss" part of each subsection
* as per the entries in the list.
*/
void app_bss_zero(void)
{ {
sys_dnode_t *node, *next_node; struct app_region *region, *end;
size_t bss_size, data_size;
SYS_DLIST_FOR_EACH_NODE_SAFE(&app_mem_list, node, next_node) end = (struct app_region *)&__app_shmem_regions_end;
{ region = (struct app_region *)&__app_shmem_regions_start;
struct app_region *region =
CONTAINER_OF(node, struct app_region, lnode);
(void)memset(region->bmem_start, 0, region->bmem_size);
}
}
/* for ( ; region < end; region++) {
* The following calculates the size of each subsection and adds /* Determine bounds and set partition appropriately */
* the computed sizes to the region structures. These calculations
* are needed both for zeroizing "bss" parts of the partitions and
* for the creation of the k_mem_partition.
*/
void app_calc_size(void)
{
sys_dnode_t *node, *next_node;
SYS_DLIST_FOR_EACH_NODE_SAFE(&app_mem_list, node, next_node)
{
#ifndef CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT #ifndef CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT
if (sys_dlist_is_tail(&app_mem_list, node)) { data_size = region->bmem_start - region->dmem_start;
struct app_region *region = if (region == end - 1) {
CONTAINER_OF(node, struct app_region, lnode); bss_size = _app_smem_end - region->bmem_start;
region->bmem_size =
_app_smem_end -
(char *)region->bmem_start;
region->dmem_size =
(char *)region->bmem_start -
(char *)region->dmem_start;
region->smem_size =
region->bmem_size + region->dmem_size;
region->partition[0].size =
region->dmem_size + region->bmem_size;
} else { } else {
struct app_region *region = struct app_region *next = region + 1;
CONTAINER_OF(node, struct app_region, lnode);
struct app_region *nRegion = __ASSERT_NO_MSG(region->bmem_start < next->dmem_start);
CONTAINER_OF(next_node, struct app_region, bss_size = next->dmem_start - region->bmem_start;
lnode);
region->bmem_size =
(char *)nRegion->dmem_start -
(char *)region->bmem_start;
region->dmem_size =
(char *)region->bmem_start -
(char *)region->dmem_start;
region->smem_size =
region->bmem_size + region->dmem_size;
region->partition[0].size =
region->dmem_size + region->bmem_size;
} }
#else #else
/* For power of 2 MPUs linker provides support to help us data_size = region->bmem_start - region->dmem_start;
* calculate the region sizes. bss_size = region->smem_size - data_size;
*/ #endif
struct app_region *region = region->partition->size = data_size + bss_size;
CONTAINER_OF(node, struct app_region, lnode);
region->dmem_size = (char *)region->bmem_start - /* Zero out BSS area of each partition */
(char *)region->dmem_start; (void)memset(region->bmem_start, 0, bss_size);
region->bmem_size = (char *)region->smem_size -
(char *)region->dmem_size;
region->partition[0].size = (s32_t)region->smem_size;
#endif /* CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT */
} }
return 0;
} }
/* SYS_INIT(app_shmem_setup, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
* "Initializes" by calculating subsection sizes and then
* zeroizing "bss" regions.
*/
void appmem_init_app_memory(void)
{
app_calc_size();
app_bss_zero();
}

View file

@ -689,24 +689,6 @@ void test_main(void)
{ {
struct k_mem_partition *parts[] = {&part0, &part1}; struct k_mem_partition *parts[] = {&part0, &part1};
/* partitions must be initialized first */
FOR_EACH(appmem_init_part, part0, part1, part2);
/*
* Next, the app_memory must be initialized in order to
* calculate size of the dynamically created subsections.
*/
#if defined(CONFIG_ARC)
/*
* appmem_init_app_memory will access all partitions
* For CONFIG_ARC_MPU_VER == 3, these partitions are not added
* into MPU now, so need to disable mpu first to do app_bss_zero()
*/
arc_core_mpu_disable();
appmem_init_app_memory();
arc_core_mpu_enable();
#else
appmem_init_app_memory();
#endif
k_mem_domain_init(&dom0, 2, parts); k_mem_domain_init(&dom0, 2, parts);
k_mem_domain_add_thread(&dom0, k_current_get()); k_mem_domain_add_thread(&dom0, k_current_get());