init: s/ARCH/EARLY, call it just before arch kernel init

The `ARCH` init level was added to solve a specific problem, call init
code (SYS_INIT/devices) before `z_cstart` in the `intel_adsp` platform.
The documentation claims it runs before `z_cstart`, but this is only
true if the SoC/arch takes care of calling:

```c
z_sys_init_run_level(_SYS_INIT_LEVEL_ARCH);
```

Which is only true for `intel_adsp` nowadays. So in practice, we now
have a platform specific init level. This patch proposes to do things in
a slightly different way. First, level name is renamed to `EARLY`, to
emphasize it runs in the early stage of the boot process. Then, it is
handled by the Kernel (inside `z_cstart()` before calling
`arch_kernel_init()`). This means that any platform can now use this
level. For `intel_adsp`, there should be no changes, other than
`gcov_static_init()` will be called before (I assume this will allow to
obtain coverage for code called in EARLY?).

Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
This commit is contained in:
Gerard Marull-Paretas 2022-10-11 17:17:18 +02:00 committed by Stephanos Ioannidis
parent b219b5cba7
commit e42f58ec94
10 changed files with 25 additions and 17 deletions

View file

@ -1,7 +1,7 @@
# originates from common-rom.ld
zephyr_linker_section(NAME init KVMA RAM_REGION GROUP RODATA_REGION)
zephyr_linker_section_obj_level(SECTION init LEVEL ARCH)
zephyr_linker_section_obj_level(SECTION init LEVEL EARLY)
zephyr_linker_section_obj_level(SECTION init LEVEL PRE_KERNEL_1)
zephyr_linker_section_obj_level(SECTION init LEVEL PRE_KERNEL_2)
zephyr_linker_section_obj_level(SECTION init LEVEL POST_KERNEL)
@ -9,7 +9,7 @@ zephyr_linker_section_obj_level(SECTION init LEVEL APPLICATION)
zephyr_linker_section_obj_level(SECTION init LEVEL SMP)
zephyr_linker_section(NAME device KVMA RAM_REGION GROUP RODATA_REGION)
zephyr_linker_section_obj_level(SECTION device LEVEL ARCH)
zephyr_linker_section_obj_level(SECTION device LEVEL EARLY)
zephyr_linker_section_obj_level(SECTION device LEVEL PRE_KERNEL_1)
zephyr_linker_section_obj_level(SECTION device LEVEL PRE_KERNEL_2)
zephyr_linker_section_obj_level(SECTION device LEVEL POST_KERNEL)

View file

@ -343,11 +343,12 @@ allow the user to specify at what time during the boot sequence the init
function will be executed. Any driver will specify one of four
initialization levels:
``ARCH``
Used very early in the boot process before ``z_cstart()`` is
called. This can be used in architectures and SoCs that extend or
implement architecture code and use drivers or system services that have
to be initialized before calling ``z_cstart()``.
``EARLY``
Used very early in the boot process, right after entering the C domain
(``z_cstart()``). This can be used in architectures and SoCs that extend
or implement architecture code and use drivers or system services that
have to be initialized before the Kernel calls any architecture specific
initialization code.
``PRE_KERNEL_1``
Used for devices that have no dependencies, such as those that rely

View file

@ -62,4 +62,4 @@ static int winstream_console_init(const struct device *d)
return 0;
}
SYS_INIT(winstream_console_init, ARCH, CONFIG_CONSOLE_INIT_PRIORITY);
SYS_INIT(winstream_console_init, EARLY, CONFIG_CONSOLE_INIT_PRIORITY);

View file

@ -22,7 +22,7 @@ extern "C" {
* stack. The remaining levels are executed in the kernel's main task.
*/
#define _SYS_INIT_LEVEL_ARCH 0
#define _SYS_INIT_LEVEL_EARLY 0
#define _SYS_INIT_LEVEL_PRE_KERNEL_1 1
#define _SYS_INIT_LEVEL_PRE_KERNEL_2 2
#define _SYS_INIT_LEVEL_POST_KERNEL 3
@ -112,6 +112,12 @@ void z_sys_init_run_level(int32_t level);
* Must be one of the following symbols, which are listed in the order
* they are performed by the kernel:
* \n
* \li EARLY: Used very early in the boot process, right after entering the C
* domain (``z_cstart()``). This can be used in architectures and SoCs that
* extend or implement architecture code and use drivers or system services that
* have to be initialized before the Kernel calls any architecture specific
* initialization code.
* \n
* \li PRE_KERNEL_1: Used for initialization objects that have no dependencies,
* such as those that rely solely on hardware present in the processor/SOC.
* These objects cannot use any kernel services during configuration, since

View file

@ -9,7 +9,7 @@
* by level, sorted by priority within a level)
*/
__init_start = .;
CREATE_OBJ_LEVEL(init, ARCH)
CREATE_OBJ_LEVEL(init, EARLY)
CREATE_OBJ_LEVEL(init, PRE_KERNEL_1)
CREATE_OBJ_LEVEL(init, PRE_KERNEL_2)
CREATE_OBJ_LEVEL(init, POST_KERNEL)
@ -25,7 +25,7 @@
* object parent. See above and include/device.h.
*/
__device_start = .;
CREATE_OBJ_LEVEL(device, ARCH)
CREATE_OBJ_LEVEL(device, EARLY)
CREATE_OBJ_LEVEL(device, PRE_KERNEL_1)
CREATE_OBJ_LEVEL(device, PRE_KERNEL_2)
CREATE_OBJ_LEVEL(device, POST_KERNEL)

View file

@ -11,7 +11,7 @@
#include <zephyr/syscall_handler.h>
extern const struct init_entry __init_start[];
extern const struct init_entry __init_ARCH_start[];
extern const struct init_entry __init_EARLY_start[];
extern const struct init_entry __init_PRE_KERNEL_1_start[];
extern const struct init_entry __init_PRE_KERNEL_2_start[];
extern const struct init_entry __init_POST_KERNEL_start[];
@ -56,7 +56,7 @@ void z_device_state_init(void)
void z_sys_init_run_level(int32_t level)
{
static const struct init_entry *levels[] = {
__init_ARCH_start,
__init_EARLY_start,
__init_PRE_KERNEL_1_start,
__init_PRE_KERNEL_2_start,
__init_POST_KERNEL_start,

View file

@ -427,6 +427,9 @@ FUNC_NORETURN void z_cstart(void)
/* gcov hook needed to get the coverage report.*/
gcov_static_init();
/* initialize early init calls */
z_sys_init_run_level(_SYS_INIT_LEVEL_EARLY);
/* perform any architecture-specific initialization */
arch_kernel_init();

View file

@ -152,8 +152,6 @@ __imr void boot_core0(void)
parse_manifest();
z_xtensa_cache_flush_all();
z_sys_init_run_level(_SYS_INIT_LEVEL_ARCH);
/* Zephyr! */
extern FUNC_NORETURN void z_cstart(void);
z_cstart();

View file

@ -29,4 +29,4 @@ int boot_complete(const struct device *d)
return 0;
}
SYS_INIT(boot_complete, ARCH, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
SYS_INIT(boot_complete, EARLY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);

View file

@ -46,7 +46,7 @@ __imr int mem_win_init(const struct device *dev)
.mem_base = DT_REG_ADDR(DT_PHANDLE(MEM_WINDOW_NODE(n), memory)) + WIN_OFFSET(n), \
.initialize = DT_PROP(MEM_WINDOW_NODE(n), initialize), \
}; \
DEVICE_DT_DEFINE(MEM_WINDOW_NODE(n), mem_win_init, NULL, NULL, &mem_win_config_##n, ARCH, \
DEVICE_DT_DEFINE(MEM_WINDOW_NODE(n), mem_win_init, NULL, NULL, &mem_win_config_##n, EARLY, \
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, NULL);
#if DT_NODE_HAS_STATUS(MEM_WINDOW_NODE(0), okay)