kernel: app_smem: allowing pinning memory partitions
This allows memory partitions to be put into the pinned section so they are available during boot. For example, the stack guard (in libc partition) is needed during boot but before the paging mechanism is initialized. Without pinning it in physical memory, it would fault in early boot process. A new cmake property app_smem,pinned_partitions is introduced so that additional partitions can be pinned if needed. Signed-off-by: Daniel Leung <daniel.leung@intel.com>
This commit is contained in:
parent
e88afd2c37
commit
2117a2a44b
|
@ -355,6 +355,7 @@ endif()
|
|||
# Declare MPU userspace dependencies before the linker scripts to make
|
||||
# sure the order of dependencies are met
|
||||
if(CONFIG_USERSPACE)
|
||||
add_custom_target(app_smem)
|
||||
set(APP_SMEM_ALIGNED_DEP app_smem_aligned_linker)
|
||||
set(APP_SMEM_UNALIGNED_DEP app_smem_unaligned_linker)
|
||||
endif()
|
||||
|
@ -985,18 +986,42 @@ toolchain_ld_configure_files()
|
|||
if(CONFIG_USERSPACE)
|
||||
set(APP_SMEM_ALIGNED_LD "${PROJECT_BINARY_DIR}/include/generated/app_smem_aligned.ld")
|
||||
set(APP_SMEM_UNALIGNED_LD "${PROJECT_BINARY_DIR}/include/generated/app_smem_unaligned.ld")
|
||||
|
||||
if(CONFIG_LINKER_USE_PINNED_SECTION)
|
||||
set(APP_SMEM_PINNED_ALIGNED_LD
|
||||
"${PROJECT_BINARY_DIR}/include/generated/app_smem_pinned_aligned.ld")
|
||||
set(APP_SMEM_PINNED_UNALIGNED_LD
|
||||
"${PROJECT_BINARY_DIR}/include/generated/app_smem_pinned_unaligned.ld")
|
||||
|
||||
if(NOT CONFIG_LINKER_GENERIC_SECTIONS_PRESENT_AT_BOOT)
|
||||
# The libc partition may hold symbols that are required during boot process,
|
||||
# for example, stack guard (if enabled). So the libc partition must be pinned
|
||||
# if not sections are in physical memory at boot, as the paging mechanism is
|
||||
# only initialized post-kernel.
|
||||
set_property(TARGET app_smem APPEND PROPERTY pinned_partitions "z_libc_partition")
|
||||
endif()
|
||||
|
||||
get_property(APP_SMEM_PINNED_PARTITION_LIST TARGET app_smem PROPERTY pinned_partitions)
|
||||
if(APP_SMEM_PINNED_PARTITION_LIST)
|
||||
list(JOIN APP_SMEM_PINNED_PARTITION_LIST "," APP_SMEM_PINNED_PARTITION_LIST_ARG_CSL)
|
||||
set(APP_SMEM_PINNED_PARTITION_LIST_ARG "--pinpartitions=${APP_SMEM_PINNED_PARTITION_LIST_ARG_CSL}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(OBJ_FILE_DIR "${PROJECT_BINARY_DIR}/../")
|
||||
|
||||
add_custom_target(
|
||||
${APP_SMEM_ALIGNED_DEP}
|
||||
DEPENDS
|
||||
${APP_SMEM_ALIGNED_LD}
|
||||
${APP_SMEM_PINNED_ALIGNED_LD}
|
||||
)
|
||||
|
||||
add_custom_target(
|
||||
${APP_SMEM_UNALIGNED_DEP}
|
||||
DEPENDS
|
||||
${APP_SMEM_UNALIGNED_LD}
|
||||
${APP_SMEM_PINNED_UNALIGNED_LD}
|
||||
)
|
||||
|
||||
if(CONFIG_NEWLIB_LIBC)
|
||||
|
@ -1007,11 +1032,13 @@ if(CONFIG_USERSPACE)
|
|||
endif()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${APP_SMEM_UNALIGNED_LD}
|
||||
OUTPUT ${APP_SMEM_UNALIGNED_LD} ${APP_SMEM_PINNED_UNALIGNED_LD}
|
||||
COMMAND ${PYTHON_EXECUTABLE}
|
||||
${ZEPHYR_BASE}/scripts/gen_app_partitions.py
|
||||
-d ${OBJ_FILE_DIR}
|
||||
-o ${APP_SMEM_UNALIGNED_LD}
|
||||
$<$<BOOL:${APP_SMEM_PINNED_UNALIGNED_LD}>:--pinoutput=${APP_SMEM_PINNED_UNALIGNED_LD}>
|
||||
${APP_SMEM_PINNED_PARTITION_LIST_ARG}
|
||||
${NEWLIB_PART}
|
||||
$<TARGET_PROPERTY:zephyr_property_target,COMPILE_OPTIONS>
|
||||
$<$<BOOL:${CMAKE_VERBOSE_MAKEFILE}>:--verbose>
|
||||
|
@ -1029,6 +1056,7 @@ if(CONFIG_USERSPACE)
|
|||
${CODE_RELOCATION_DEP}
|
||||
${APP_SMEM_UNALIGNED_DEP}
|
||||
${APP_SMEM_UNALIGNED_LD}
|
||||
${APP_SMEM_PINNED_UNALIGNED_LD}
|
||||
zephyr_generated_headers
|
||||
)
|
||||
|
||||
|
@ -1061,11 +1089,13 @@ if(CONFIG_USERSPACE)
|
|||
add_dependencies( app_smem_unaligned_prebuilt linker_app_smem_unaligned_script ${OFFSETS_LIB})
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${APP_SMEM_ALIGNED_LD}
|
||||
OUTPUT ${APP_SMEM_ALIGNED_LD} ${APP_SMEM_PINNED_ALIGNED_LD}
|
||||
COMMAND ${PYTHON_EXECUTABLE}
|
||||
${ZEPHYR_BASE}/scripts/gen_app_partitions.py
|
||||
-e $<TARGET_FILE:app_smem_unaligned_prebuilt>
|
||||
-o ${APP_SMEM_ALIGNED_LD}
|
||||
$<$<BOOL:${APP_SMEM_PINNED_ALIGNED_LD}>:--pinoutput=${APP_SMEM_PINNED_ALIGNED_LD}>
|
||||
${APP_SMEM_PINNED_PARTITION_LIST_ARG}
|
||||
${NEWLIB_PART}
|
||||
$<TARGET_PROPERTY:zephyr_property_target,COMPILE_OPTIONS>
|
||||
$<$<BOOL:${CMAKE_VERBOSE_MAKEFILE}>:--verbose>
|
||||
|
|
|
@ -18,4 +18,18 @@ macro(toolchain_ld_configure_files)
|
|||
configure_file(
|
||||
${ZEPHYR_BASE}/include/linker/app_smem_unaligned.ld
|
||||
${PROJECT_BINARY_DIR}/include/generated/app_smem_unaligned.ld)
|
||||
|
||||
if(CONFIG_LINKER_USE_PINNED_SECTION)
|
||||
configure_file(
|
||||
${ZEPHYR_BASE}/include/linker/app_smem_pinned.ld
|
||||
${PROJECT_BINARY_DIR}/include/generated/app_smem_pinned.ld)
|
||||
|
||||
configure_file(
|
||||
${ZEPHYR_BASE}/include/linker/app_smem_pinned_aligned.ld
|
||||
${PROJECT_BINARY_DIR}/include/generated/app_smem_pinned_aligned.ld)
|
||||
|
||||
configure_file(
|
||||
${ZEPHYR_BASE}/include/linker/app_smem_pinned_unaligned.ld
|
||||
${PROJECT_BINARY_DIR}/include/generated/app_smem_pinned_unaligned.ld)
|
||||
endif()
|
||||
endmacro()
|
||||
|
|
42
include/linker/app_smem_pinned.ld
Normal file
42
include/linker/app_smem_pinned.ld
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Intel Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* This hackish way of including files is due to CMake issues:
|
||||
* https://gitlab.kitware.com/cmake/cmake/issues/11985
|
||||
* https://gitlab.kitware.com/cmake/cmake/issues/13718
|
||||
*
|
||||
* When using the "Unix Makefiles" generator, CMake simply
|
||||
* greps for "#include" to generate dependency list.
|
||||
* So if doing it normally, both files are being included
|
||||
* in the dependency list. This creates weird dependency
|
||||
* issue:
|
||||
*
|
||||
* 1. Using A.ld to create a linker script A.cmd.
|
||||
* 2. Using A.cmd to generate A_prebuilt.elf.
|
||||
* 3. Using A_prebuilt.elf to create B.ld.
|
||||
* 4. Creating B.cmd with B.ld.
|
||||
* 5. Creating B_prebuilt.elf using B.cmd.
|
||||
*
|
||||
* Since the dependency list of A.cmd contains both
|
||||
* A.ld and B.ld, when make is invoked again, B.ld
|
||||
* is newer than A.cmd so everything from this point on
|
||||
* gets rebuilt. In order to break this cycle, this
|
||||
* hackish needs to be used since CMake does not parse
|
||||
* macros, and thus these will not appear in
|
||||
* the dependency list. The dependencies should then be
|
||||
* put in CMakeLists.txt instead.
|
||||
*
|
||||
* Note: Ninja generator does not suffer from this issue.
|
||||
*/
|
||||
#ifdef LINKER_APP_SMEM_UNALIGNED
|
||||
#define APP_SMEM_LD <app_smem_pinned_unaligned.ld>
|
||||
#else
|
||||
#define APP_SMEM_LD <app_smem_pinned_aligned.ld>
|
||||
#endif
|
||||
|
||||
#include APP_SMEM_LD
|
||||
#undef APP_SMEM_LD
|
7
include/linker/app_smem_pinned_aligned.ld
Normal file
7
include/linker/app_smem_pinned_aligned.ld
Normal file
|
@ -0,0 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Intel Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* Empty file */
|
7
include/linker/app_smem_pinned_unaligned.ld
Normal file
7
include/linker/app_smem_pinned_unaligned.ld
Normal file
|
@ -0,0 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Intel Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* Empty file */
|
|
@ -197,6 +197,13 @@ extern char _app_smem_size[];
|
|||
extern char _app_smem_rom_start[];
|
||||
extern char _app_smem_num_words[];
|
||||
|
||||
#ifdef CONFIG_LINKER_USE_PINNED_SECTION
|
||||
extern char _app_smem_pinned_start[];
|
||||
extern char _app_smem_pinned_end[];
|
||||
extern char _app_smem_pinned_size[];
|
||||
extern char _app_smem_pinned_num_words[];
|
||||
#endif
|
||||
|
||||
/* Memory owned by the kernel. Start and end will be aligned for memory
|
||||
* management/protection hardware for the target architecture.
|
||||
*
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#define _APP_BSS_SECTION_NAME app_bss
|
||||
#define _APP_NOINIT_SECTION_NAME app_noinit
|
||||
|
||||
#define _APP_SMEM_PINNED_SECTION_NAME app_smem_pinned
|
||||
|
||||
#define _UNDEFINED_SECTION_NAME undefined
|
||||
|
||||
/* Interrupts */
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <sys/libc-hooks.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <inttypes.h>
|
||||
#include <linker/linker-defs.h>
|
||||
|
||||
#ifdef Z_LIBC_PARTITION_EXISTS
|
||||
K_APPMEM_PARTITION_DEFINE(z_libc_partition);
|
||||
|
@ -859,7 +860,29 @@ static int app_shmem_bss_zero(const struct device *unused)
|
|||
region = (struct z_app_region *)&__app_shmem_regions_start;
|
||||
|
||||
for ( ; region < end; region++) {
|
||||
(void)memset(region->bss_start, 0, region->bss_size);
|
||||
#if defined(CONFIG_DEMAND_PAGING) && !defined(CONFIG_LINKER_GENERIC_SECTIONS_PRESENT_AT_BOOT)
|
||||
/* When BSS sections are not present at boot, we need to wait for
|
||||
* paging mechanism to be initialized before we can zero out BSS.
|
||||
*/
|
||||
extern bool z_sys_post_kernel;
|
||||
bool do_clear = z_sys_post_kernel;
|
||||
|
||||
/* During pre-kernel init, z_sys_post_kernel == false, but
|
||||
* with pinned rodata region, so clear. Otherwise skip.
|
||||
* In post-kernel init, z_sys_post_kernel == true,
|
||||
* skip those in pinned rodata region as they have already
|
||||
* been cleared and possibly already in use. Otherwise clear.
|
||||
*/
|
||||
if (((uint8_t *)region->bss_start >= (uint8_t *)_app_smem_pinned_start) &&
|
||||
((uint8_t *)region->bss_start < (uint8_t *)_app_smem_pinned_end)) {
|
||||
do_clear = !do_clear;
|
||||
}
|
||||
|
||||
if (do_clear)
|
||||
#endif /* CONFIG_DEMAND_PAGING && !CONFIG_LINKER_GENERIC_SECTIONS_PRESENT_AT_BOOT */
|
||||
{
|
||||
(void)memset(region->bss_start, 0, region->bss_size);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -867,6 +890,13 @@ static int app_shmem_bss_zero(const struct device *unused)
|
|||
|
||||
SYS_INIT(app_shmem_bss_zero, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
||||
|
||||
#if defined(CONFIG_DEMAND_PAGING) && !defined(CONFIG_LINKER_GENERIC_SECTIONS_PRESENT_AT_BOOT)
|
||||
/* When BSS sections are not present at boot, we need to wait for
|
||||
* paging mechanism to be initialized before we can zero out BSS.
|
||||
*/
|
||||
SYS_INIT(app_shmem_bss_zero, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
||||
#endif /* CONFIG_DEMAND_PAGING && !CONFIG_LINKER_GENERIC_SECTIONS_PRESENT_AT_BOOT */
|
||||
|
||||
/*
|
||||
* Default handlers if otherwise unimplemented
|
||||
*/
|
||||
|
|
|
@ -75,16 +75,24 @@ footer_template = """
|
|||
"""
|
||||
|
||||
linker_start_seq = """
|
||||
SECTION_PROLOGUE(_APP_SMEM_SECTION_NAME,,)
|
||||
{
|
||||
SECTION_PROLOGUE(_APP_SMEM{1}_SECTION_NAME,,)
|
||||
{{
|
||||
APP_SHARED_ALIGN;
|
||||
_app_smem_start = .;
|
||||
_app_smem{0}_start = .;
|
||||
"""
|
||||
|
||||
linker_end_seq = """
|
||||
APP_SHARED_ALIGN;
|
||||
_app_smem_end = .;
|
||||
} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
|
||||
_app_smem{0}_end = .;
|
||||
}} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
|
||||
"""
|
||||
|
||||
empty_app_smem = """
|
||||
SECTION_PROLOGUE(_APP_SMEM{1}_SECTION_NAME,,)
|
||||
{{
|
||||
_app_smem{0}_start = .;
|
||||
_app_smem{0}_end = .;
|
||||
}} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
|
||||
"""
|
||||
|
||||
size_cal_string = """
|
||||
|
@ -159,23 +167,29 @@ def parse_elf_file(partitions):
|
|||
partitions[partition_name][SZ] += size
|
||||
|
||||
|
||||
def generate_final_linker(linker_file, partitions):
|
||||
string = linker_start_seq
|
||||
size_string = ''
|
||||
for partition, item in partitions.items():
|
||||
string += data_template.format(partition)
|
||||
if LIB in item:
|
||||
for lib in item[LIB]:
|
||||
string += library_data_template.format(lib)
|
||||
string += bss_template.format(partition)
|
||||
if LIB in item:
|
||||
for lib in item[LIB]:
|
||||
string += library_bss_template.format(lib)
|
||||
string += footer_template.format(partition)
|
||||
size_string += size_cal_string.format(partition)
|
||||
def generate_final_linker(linker_file, partitions, lnkr_sect=""):
|
||||
string = ""
|
||||
|
||||
if len(partitions) > 0:
|
||||
string = linker_start_seq.format(lnkr_sect, lnkr_sect.upper())
|
||||
size_string = ''
|
||||
for partition, item in partitions.items():
|
||||
string += data_template.format(partition)
|
||||
if LIB in item:
|
||||
for lib in item[LIB]:
|
||||
string += library_data_template.format(lib)
|
||||
string += bss_template.format(partition, lnkr_sect)
|
||||
if LIB in item:
|
||||
for lib in item[LIB]:
|
||||
string += library_bss_template.format(lib)
|
||||
string += footer_template.format(partition)
|
||||
size_string += size_cal_string.format(partition)
|
||||
|
||||
string += linker_end_seq.format(lnkr_sect)
|
||||
string += size_string
|
||||
else:
|
||||
string = empty_app_smem.format(lnkr_sect, lnkr_sect.upper())
|
||||
|
||||
string += linker_end_seq
|
||||
string += size_string
|
||||
with open(linker_file, "w") as fw:
|
||||
fw.write(string)
|
||||
|
||||
|
@ -196,6 +210,10 @@ def parse_args():
|
|||
parser.add_argument("-l", "--library", nargs=2, action="append", default=[],
|
||||
metavar=("LIBRARY", "PARTITION"),
|
||||
help="Include globals for a particular library or object filename into a designated partition")
|
||||
parser.add_argument("--pinoutput", required=False,
|
||||
help="Output ld file for pinned sections")
|
||||
parser.add_argument("--pinpartitions", action="store", required=False, default="",
|
||||
help="Comma separated names of partitions to be pinned in physical memory")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
|
@ -220,11 +238,20 @@ def main():
|
|||
else:
|
||||
partitions[ptn][LIB].append(lib)
|
||||
|
||||
if args.pinoutput:
|
||||
pin_part_names = args.pinpartitions.split(',')
|
||||
|
||||
generic_partitions = {key: value for key, value in partitions.items()
|
||||
if key not in pin_part_names}
|
||||
pinned_partitions = {key: value for key, value in partitions.items()
|
||||
if key in pin_part_names}
|
||||
else:
|
||||
generic_partitions = partitions
|
||||
|
||||
# Sample partitions.items() list before sorting:
|
||||
# [ ('part1', {'size': 64}), ('part3', {'size': 64}, ...
|
||||
# ('part0', {'size': 334}) ]
|
||||
decreasing_tuples = sorted(partitions.items(),
|
||||
decreasing_tuples = sorted(generic_partitions.items(),
|
||||
key=lambda x: (x[1][SZ], x[0]), reverse=True)
|
||||
|
||||
partsorted = OrderedDict(decreasing_tuples)
|
||||
|
@ -237,6 +264,20 @@ def main():
|
|||
partsorted[key][SZ],
|
||||
partsorted[key][SRC]))
|
||||
|
||||
if args.pinoutput:
|
||||
decreasing_tuples = sorted(pinned_partitions.items(),
|
||||
key=lambda x: (x[1][SZ], x[0]), reverse=True)
|
||||
|
||||
partsorted = OrderedDict(decreasing_tuples)
|
||||
|
||||
generate_final_linker(args.pinoutput, partsorted, lnkr_sect="_pinned")
|
||||
if args.verbose:
|
||||
print("Pinned partitions retrieved:")
|
||||
for key in partsorted:
|
||||
print(" {0}: size {1}: {2}".format(key,
|
||||
partsorted[key][SZ],
|
||||
partsorted[key][SRC]))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
@ -514,6 +514,14 @@ def find_kobjects(elf, syms):
|
|||
|
||||
app_smem_start = syms["_app_smem_start"]
|
||||
app_smem_end = syms["_app_smem_end"]
|
||||
|
||||
if "CONFIG_LINKER_USE_PINNED_SECTION" in syms and "_app_smem_pinned_start" in syms:
|
||||
app_smem_pinned_start = syms["_app_smem_pinned_start"]
|
||||
app_smem_pinned_end = syms["_app_smem_pinned_end"]
|
||||
else:
|
||||
app_smem_pinned_start = app_smem_start
|
||||
app_smem_pinned_end = app_smem_end
|
||||
|
||||
user_stack_start = syms["z_user_stacks_start"]
|
||||
user_stack_end = syms["z_user_stacks_end"]
|
||||
|
||||
|
@ -630,7 +638,9 @@ def find_kobjects(elf, syms):
|
|||
continue
|
||||
|
||||
_, user_ram_allowed, _ = kobjects[ko.type_obj.name]
|
||||
if not user_ram_allowed and app_smem_start <= addr < app_smem_end:
|
||||
if (not user_ram_allowed and
|
||||
((app_smem_start <= addr < app_smem_end)
|
||||
or (app_smem_pinned_start <= addr < app_smem_pinned_end))):
|
||||
debug("object '%s' found in invalid location %s"
|
||||
% (ko.type_obj.name, hex(addr)))
|
||||
continue
|
||||
|
|
Loading…
Reference in a new issue