diff --git a/CMakeLists.txt b/CMakeLists.txt index 0e1d3df2ab5..f46dfe572a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -350,6 +350,10 @@ if(CONFIG_USERSPACE) set(APP_SMEM_UNALIGNED_DEP app_smem_unaligned_linker) endif() +if(CONFIG_USERSPACE) + set(KOBJECT_LINKER_DEP kobject_linker) +endif() + get_property(TOPT GLOBAL PROPERTY TOPT) set_ifndef( TOPT -Wl,-T) # clang doesn't pick -T for some reason and complains, # while -Wl,-T works for both, gcc and clang @@ -847,6 +851,7 @@ if(CONFIG_USERSPACE) COMMAND ${GPERF} --output-file ${KOBJECT_HASH_OUTPUT_SRC_PRE} + --multiple-iterations 10 ${KOBJECT_HASH_LIST} DEPENDS kobj_hash_list ${KOBJECT_HASH_LIST} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} @@ -1062,10 +1067,137 @@ if(CONFIG_USERSPACE) ) endif() +if(CONFIG_USERSPACE) + # This CONFIG_USERSPACE block is to create place holders to reserve space + # for the gperf generated structures for zephyr_prebuilt.elf. + # These place holders are there so that the placement of kobjects would be + # the same between linking zephyr_prebuilt.elf and zephyr.elf, as + # the gperf hash table is hashed on the addresses of kobjects. + # The placeholders are generated from app_smem_unaligned_prebuilt.elf. + + set(KOBJECT_PREBUILT_HASH_LIST kobject_prebuilt_hash.gperf) + set(KOBJECT_PREBUILT_HASH_OUTPUT_SRC_PRE kobject_prebuilt_hash_preprocessed.c) + set(KOBJECT_PREBUILT_HASH_OUTPUT_SRC kobject_prebuilt_hash.c) + set(KOBJECT_PREBUILT_HASH_OUTPUT_OBJ kobject_prebuilt_hash.c.obj) + + add_custom_command( + OUTPUT ${KOBJECT_PREBUILT_HASH_LIST} + COMMAND + ${PYTHON_EXECUTABLE} + ${GEN_KOBJ_LIST} + --kernel $ + --gperf-output ${KOBJECT_PREBUILT_HASH_LIST} + ${gen_kobject_list_include_args} + $<$:--verbose> + DEPENDS + app_smem_unaligned_prebuilt + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + ) + add_custom_target( + kobj_prebuilt_hash_list + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${KOBJECT_PREBUILT_HASH_LIST} + ) + + add_custom_command( + OUTPUT ${KOBJECT_PREBUILT_HASH_OUTPUT_SRC_PRE} + COMMAND + ${GPERF} + --output-file ${KOBJECT_PREBUILT_HASH_OUTPUT_SRC_PRE} + --multiple-iterations 10 + ${KOBJECT_PREBUILT_HASH_LIST} + DEPENDS kobj_prebuilt_hash_list ${KOBJECT_PREBUILT_HASH_LIST} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + ) + add_custom_target( + kobj_prebuilt_hash_output_src_pre + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${KOBJECT_PREBUILT_HASH_OUTPUT_SRC_PRE} + ) + + add_custom_command( + OUTPUT ${KOBJECT_PREBUILT_HASH_OUTPUT_SRC} + COMMAND + ${PYTHON_EXECUTABLE} + ${PROCESS_GPERF} + -i ${KOBJECT_PREBUILT_HASH_OUTPUT_SRC_PRE} + -o ${KOBJECT_PREBUILT_HASH_OUTPUT_SRC} + -p "struct z_object" + $<$:--verbose> + DEPENDS kobj_prebuilt_hash_output_src_pre ${KOBJECT_PREBUILT_HASH_OUTPUT_SRC_PRE} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + ) + add_custom_target( + kobj_prebuilt_hash_output_src + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${KOBJECT_PREBUILT_HASH_OUTPUT_SRC} + ) + + add_library( + kobj_prebuilt_hash_output_lib + STATIC ${CMAKE_CURRENT_BINARY_DIR}/${KOBJECT_PREBUILT_HASH_OUTPUT_SRC} + ) + + set_source_files_properties(${KOBJECT_PREBUILT_HASH_OUTPUT_SRC} + PROPERTIES COMPILE_FLAGS + "${NO_COVERAGE_FLAGS} -fno-function-sections -fno-data-sections") + + set_source_files_properties(${KOBJECT_PREBUILT_HASH_OUTPUT_SRC} + PROPERTIES COMPILE_DEFINITIONS "${compile_definitions_interface}") + + add_library(kobj_prebuilt_hash_output_lib_interface INTERFACE) + + target_link_libraries( + kobj_prebuilt_hash_output_lib + kobj_prebuilt_hash_output_lib_interface + ) + + foreach(incl ${include_dir_in_interface}) + target_include_directories( + kobj_prebuilt_hash_output_lib_interface + INTERFACE ${incl} + ) + endforeach() + + foreach(incl ${sys_include_dir_in_interface}) + target_include_directories( + kobj_prebuilt_hash_output_lib_interface + SYSTEM INTERFACE ${incl} + ) + endforeach() + + set( + KOBJECT_PREBUILT_HASH_OUTPUT_OBJ_PATH + ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/kobj_prebuilt_hash_output_lib.dir/${KOBJECT_PREBUILT_HASH_OUTPUT_OBJ} + ) + + set(KOBJECT_LINKER_HEADER_DATA "${PROJECT_BINARY_DIR}/include/generated/linker-kobject-prebuilt-data.h") + + add_custom_command( + OUTPUT ${KOBJECT_LINKER_HEADER_DATA} + COMMAND + ${PYTHON_EXECUTABLE} + ${ZEPHYR_BASE}/scripts/gen_kobject_placeholders.py + --object ${KOBJECT_PREBUILT_HASH_OUTPUT_OBJ_PATH} + --outdir ${PROJECT_BINARY_DIR}/include/generated + --datapct ${CONFIG_KOBJECT_DATA_AREA_RESERVE_EXTRA_PERCENT} + --rodata ${CONFIG_KOBJECT_RODATA_AREA_EXTRA_BYTES} + $<$:--verbose> + DEPENDS + kobj_prebuilt_hash_output_lib + ${KOBJECT_PREBUILT_HASH_OUTPUT_OBJ_PATH} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + ) + + add_custom_target( + ${KOBJECT_LINKER_DEP} + DEPENDS + ${KOBJECT_LINKER_HEADER_DATA} + ) +endif() + configure_linker_script( linker_zephyr_prebuilt.cmd "-DLINKER_ZEPHYR_PREBUILT" ${APP_SMEM_ALIGNED_DEP} + ${KOBJECT_LINKER_DEP} ${CODE_RELOCATION_DEP} zephyr_generated_headers ) diff --git a/CODEOWNERS b/CODEOWNERS index a4271facd73..e81e1dfd38a 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -547,6 +547,7 @@ /arch/x86/gen_gdt.py @dcpleung @nashif /arch/x86/gen_idt.py @dcpleung @nashif /scripts/gen_kobject_list.py @dcpleung @nashif +/scripts/gen_kobject_placeholders.py @dcpleung /scripts/gen_syscalls.py @dcpleung @nashif /scripts/list_boards.py @mbolivar-nordic /scripts/net/ @jukkar diff --git a/arch/Kconfig b/arch/Kconfig index 00967ee2a57..3061d82cdbe 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -273,7 +273,7 @@ config PRIVILEGED_STACK_SIZE a multiple of the minimum stack alignment. config KOBJECT_TEXT_AREA - int "Size if kobject text area" + int "Size of kobject text area" default 512 if COVERAGE_GCOV default 512 if NO_OPTIMIZATIONS default 512 if STACK_CANARIES && RISCV @@ -282,6 +282,28 @@ config KOBJECT_TEXT_AREA help Size of kernel object text area. Used in linker script. +config KOBJECT_DATA_AREA_RESERVE_EXTRA_PERCENT + int "Reserve extra kobject data area (in percentage)" + default 100 + depends on ARCH_HAS_USERSPACE + help + Multiplication factor used to calculate the size of placeholder to + reserve space for kobject metadata hash table. The hash table is + generated via gperf is highly dependent on the absolute addresses of + kobjects which might change between prebuilts. To reserve enough + space for the hash table during final linking passes to keep + kobjects in same place, the size of reserved space is calculated + from the first prebuilt plus additional space calculated with + this percentage (of the kobject data area in first prebuilt). + +config KOBJECT_RODATA_AREA_EXTRA_BYTES + int "Reserve extra bytes for kobject rodata area" + default 16 + depends on ARCH_HAS_USERSPACE + help + Reserve a few more bytes for the RODATA region for kobject metadata. + This is to account for the uncertainty of tables generated by gperf. + config GEN_PRIV_STACKS bool help diff --git a/include/arch/arc/v2/linker.ld b/include/arch/arc/v2/linker.ld index e5398952529..25ceca7c995 100644 --- a/include/arch/arc/v2/linker.ld +++ b/include/arch/arc/v2/linker.ld @@ -188,7 +188,7 @@ SECTIONS { __data_rom_start = LOADADDR(_DATA_SECTION_NAME); #include -#include +#include #ifdef __MWDT_LINKER_CMD__ /* TODO: add mwdt specific RAM C++ sections */ diff --git a/include/arch/arm/aarch32/cortex_a_r/scripts/linker.ld b/include/arch/arm/aarch32/cortex_a_r/scripts/linker.ld index def88f5a99b..1501151572d 100644 --- a/include/arch/arm/aarch32/cortex_a_r/scripts/linker.ld +++ b/include/arch/arm/aarch32/cortex_a_r/scripts/linker.ld @@ -295,7 +295,7 @@ SECTIONS __data_rom_start = LOADADDR(_DATA_SECTION_NAME); #include -#include +#include #include __data_ram_end = .; diff --git a/include/arch/arm/aarch32/cortex_m/scripts/linker.ld b/include/arch/arm/aarch32/cortex_m/scripts/linker.ld index d07b7b12617..adf43203116 100644 --- a/include/arch/arm/aarch32/cortex_m/scripts/linker.ld +++ b/include/arch/arm/aarch32/cortex_m/scripts/linker.ld @@ -329,7 +329,7 @@ SECTIONS __data_rom_start = LOADADDR(_DATA_SECTION_NAME); #include -#include +#include #include diff --git a/include/arch/arm64/scripts/linker.ld b/include/arch/arm64/scripts/linker.ld index d9710aa344d..47812a9f979 100644 --- a/include/arch/arm64/scripts/linker.ld +++ b/include/arch/arm64/scripts/linker.ld @@ -271,7 +271,7 @@ SECTIONS __data_rom_start = LOADADDR(_DATA_SECTION_NAME); #include -#include +#include #include __data_ram_end = .; diff --git a/include/arch/riscv/common/linker.ld b/include/arch/riscv/common/linker.ld index 6560e7f9e3e..f5db23cd278 100644 --- a/include/arch/riscv/common/linker.ld +++ b/include/arch/riscv/common/linker.ld @@ -225,7 +225,7 @@ SECTIONS __data_rom_start = LOADADDR(_DATA_SECTION_NAME); #include -#include +#include /* Located in generated directory. This file is populated by the * zephyr_linker_sources() Cmake function. diff --git a/include/arch/x86/ia32/linker.ld b/include/arch/x86/ia32/linker.ld index 9eba72d0657..d71620f4761 100644 --- a/include/arch/x86/ia32/linker.ld +++ b/include/arch/x86/ia32/linker.ld @@ -336,7 +336,7 @@ SECTIONS #include /* Must be last in RAM */ -#include +#include MMU_PAGE_ALIGN __data_ram_end = .; diff --git a/include/arch/x86/intel64/linker.ld b/include/arch/x86/intel64/linker.ld index 7eb9987544f..e149276b616 100644 --- a/include/arch/x86/intel64/linker.ld +++ b/include/arch/x86/intel64/linker.ld @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Intel Corp. + * Copyright (c) 2019-2021 Intel Corp. * SPDX-License-Identifier: Apache-2.0 */ @@ -185,7 +185,7 @@ SECTIONS #include /* Must be last in RAM */ -#include +#include MMU_PAGE_ALIGN _image_ram_end = .; z_mapped_end = .; diff --git a/include/linker/common-noinit.ld b/include/linker/common-noinit.ld index bf940c8ae68..fba2221162b 100644 --- a/include/linker/common-noinit.ld +++ b/include/linker/common-noinit.ld @@ -24,3 +24,5 @@ SECTION_PROLOGUE(_NOINIT_SECTION_NAME,(NOLOAD),) #include } GROUP_NOLOAD_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + +#include "kobject-priv-stacks.ld" diff --git a/include/linker/kobject-data.ld b/include/linker/kobject-data.ld new file mode 100644 index 00000000000..bb258158c45 --- /dev/null +++ b/include/linker/kobject-data.ld @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2017,2021 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifdef CONFIG_USERSPACE + + z_kobject_data_begin = .; + SECTION_DATA_PROLOGUE(kobject_data,,) + { + +#if !defined(LINKER_ZEPHYR_PREBUILT) && \ + !defined(LINKER_ZEPHYR_FINAL) + +#ifdef CONFIG_DYNAMIC_OBJECTS + PROVIDE(_thread_idx_map = .); + . += CONFIG_MAX_THREAD_BYTES; +#endif + +#endif /* !LINKER_ZEPHYR_PREBUILT && !LINKER_ZEPHYR_FINAL */ + + /* During LINKER_KOBJECT_PREBUILT and LINKER_ZEPHYR_PREBUILT, + * space needs to be reserved for the rodata that will be + * produced by gperf during the final stages of linking. + * The alignment and size are produced by + * scripts/gen_kobject_placeholders.py. These are here + * so the addresses to kobjects would remain the same + * during the final stages of linking (LINKER_ZEPHYR_FINAL). + */ + +#if defined(LINKER_ZEPHYR_PREBUILT) +#include + +#ifdef CONFIG_DYNAMIC_OBJECTS + /* This is produced by gperf. Put a place holder here + * to avoid compilation error. + */ + PROVIDE(_thread_idx_map = .); +#endif +#ifdef KOBJECT_DATA_ALIGN + . = ALIGN(KOBJECT_DATA_ALIGN); + . += KOBJECT_DATA_SZ; +#endif +#endif /* LINKER_ZEPHYR_PREBUILT */ + +#if defined(LINKER_ZEPHYR_FINAL) +#include +#ifdef KOBJECT_DATA_ALIGN + . = ALIGN(KOBJECT_DATA_ALIGN); + + _kobject_data_area_start = .; +#endif + + *(".kobject_data.data*") + +#ifdef KOBJECT_DATA_ALIGN + _kobject_data_area_end = .; + _kobject_data_area_used = _kobject_data_area_end - _kobject_data_area_start; + + ASSERT(_kobject_data_area_used <= KOBJECT_DATA_SZ, +"scripts/gen_kobject_placeholders.py did not reserve enough space \ +for kobject data." + ); + + /* Padding is needed to preserve kobject addresses + * if we have reserved more space than needed. + */ + . = MAX(., _kobject_data_area_start + KOBJECT_DATA_SZ); +#endif /* KOBJECT_DATA_ALIGN */ +#endif /* LINKER_ZEPHYR_FINAL */ + + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + +#endif /* CONFIG_USERSPACE */ diff --git a/include/linker/kobject-priv-stacks.ld b/include/linker/kobject-priv-stacks.ld new file mode 100644 index 00000000000..94861db22cd --- /dev/null +++ b/include/linker/kobject-priv-stacks.ld @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2017,2021 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifdef CONFIG_USERSPACE +#ifdef CONFIG_GEN_PRIV_STACKS + SECTION_DATA_PROLOGUE(priv_stacks_noinit,,) + { + z_priv_stacks_ram_start = .; + + /* During LINKER_KOBJECT_PREBUILT and LINKER_ZEPHYR_PREBUILT, + * space needs to be reserved for the rodata that will be + * produced by gperf during the final stages of linking. + * The alignment and size are produced by + * scripts/gen_kobject_placeholders.py. These are here + * so the addresses to kobjects would remain the same + * during the final stages of linking (LINKER_ZEPHYR_FINAL). + */ + +#if defined(LINKER_ZEPHYR_PREBUILT) +#include +#ifdef KOBJECT_PRIV_STACKS_ALIGN + . = ALIGN(KOBJECT_PRIV_STACKS_ALIGN); + . += KOBJECT_PRIV_STACKS_SZ; +#endif +#endif /* LINKER_ZEPHYR_PREBUILT */ + +#if defined(LINKER_ZEPHYR_FINAL) +#include +#ifdef KOBJECT_PRIV_STACKS_ALIGN + . = ALIGN(KOBJECT_PRIV_STACKS_ALIGN); +#endif + *(".priv_stacks.noinit") +#endif /* LINKER_ZEPHYR_FINAL */ + + z_priv_stacks_ram_end = .; + +#if defined(LINKER_ZEPHYR_FINAL) +#ifdef KOBJECT_PRIV_STACKS_ALIGN + z_priv_stacks_ram_used = z_priv_stacks_ram_end - z_priv_stacks_ram_start; + + ASSERT(z_priv_stacks_ram_used <= KOBJECT_PRIV_STACKS_SZ, +"scripts/gen_kobject_placeholders.py did not reserve enough space \ +for priviledged stacks." + ); + + /* Padding is needed to preserve kobject addresses + * if we have reserved more space than needed. + */ + . = MAX(., z_priv_stacks_ram_start + KOBJECT_PRIV_STACKS_SZ); +#endif /* KOBJECT_PRIV_STACKS_ALIGN */ +#endif /* LINKER_ZEPHYR_FINAL */ + + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) +#endif /* CONFIG_GEN_PRIV_STACKS */ +#endif /* CONFIG_USERSPACE */ diff --git a/include/linker/kobject-rom.ld b/include/linker/kobject-rom.ld index 66f5a4ec300..4b03bc8565c 100644 --- a/include/linker/kobject-rom.ld +++ b/include/linker/kobject-rom.ld @@ -1,13 +1,57 @@ /* - * Copyright (c) 2017 Intel Corporation + * Copyright (c) 2017,2021 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #ifdef CONFIG_USERSPACE - /* Kept in RAM on non-XIP */ -#ifdef CONFIG_XIP - *(".kobject_data.rodata*") -#endif -#endif /* CONFIG_USERSPACE */ + /* During LINKER_KOBJECT_PREBUILT and LINKER_ZEPHYR_PREBUILT, + * space needs to be reserved for the rodata that will be + * produced by gperf during the final stages of linking. + * The alignment and size are produced by + * scripts/gen_kobject_placeholders.py. These are here + * so the addresses to kobjects would remain the same + * during the final stages of linking (LINKER_ZEPHYR_FINAL). + */ + +#if defined(LINKER_ZEPHYR_PREBUILT) +#include +#ifdef KOBJECT_RODATA_ALIGN + . = ALIGN(KOBJECT_RODATA_ALIGN); + + _kobject_rodata_area_start = .; + + . += KOBJECT_RODATA_SZ; + + _kobject_rodata_area_end = .; +#endif +#endif /* LINKER_ZEPHYR_PREBUILT */ + +#if defined(LINKER_ZEPHYR_FINAL) +#include +#ifdef KOBJECT_RODATA_ALIGN + . = ALIGN(KOBJECT_RODATA_ALIGN); + + _kobject_rodata_area_start = .; +#endif + + *(".kobject_data.rodata*") + +#ifdef KOBJECT_RODATA_ALIGN + _kobject_rodata_area_end = .; + _kobject_rodata_area_used = _kobject_rodata_area_end - _kobject_rodata_area_start; + + ASSERT(_kobject_rodata_area_used <= KOBJECT_RODATA_SZ, +"scripts/gen_kobject_placeholders.py did not reserve enough space \ +for kobject rodata." + ); + + /* Padding is needed to preserve kobject addresses + * if we have reserved more space than needed. + */ + . = MAX(., _kobject_rodata_area_start + KOBJECT_RODATA_SZ); +#endif /* KOBJECT_RODATA_ALIGN */ +#endif /* LINKER_ZEPHYR_FINAL */ + +#endif /* CONFIG_USERSPACE */ diff --git a/include/linker/kobject.ld b/include/linker/kobject.ld deleted file mode 100644 index 114347e690f..00000000000 --- a/include/linker/kobject.ld +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifdef CONFIG_USERSPACE - z_kobject_data_begin = .; - /* Constraints: - * - * - changes to the size of this section between build phases - * *must not* shift the memory address of any kernel obejcts, - * since it contains a hashtable of the memory addresses of those - * kernel objects - * - * - It is OK if this section itself is shifted in between builds; for - * example some arches may precede this section with generated MMU - * page tables which are also unpredictable in size. - * - * The size of the - * gperf tables is both a function of the number of kernel objects, - * *and* the specific memory addresses being hashed. It is not something - * that can be predicted without actually building and compling it. - */ - SECTION_DATA_PROLOGUE(kobject_data,,) - { - *(".kobject_data.data*") - -#ifndef LINKER_ZEPHYR_FINAL -#ifdef CONFIG_DYNAMIC_OBJECTS - PROVIDE(_thread_idx_map = .); - . += CONFIG_MAX_THREAD_BYTES; -#endif -#endif - - /* This is also unpredictable in size, and has the same constraints. - * On XIP systems this will get put at the very end of ROM. - */ -#ifndef CONFIG_XIP - *(".kobject_data.rodata*") -#endif - } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) - -#ifdef CONFIG_GEN_PRIV_STACKS - SECTION_DATA_PROLOGUE(priv_stacks_noinit,,) - { - z_priv_stacks_ram_start = .; - *(".priv_stacks.noinit") - z_priv_stacks_ram_end = .; - } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) -#endif /* CONFIG_GEN_PRIV_STACKS */ -#endif /* CONFIG_USERSPACE */ diff --git a/kernel/include/kernel_internal.h b/kernel/include/kernel_internal.h index d377d736bc8..0eaffbfa161 100644 --- a/kernel/include/kernel_internal.h +++ b/kernel/include/kernel_internal.h @@ -199,9 +199,6 @@ void z_thread_mark_switched_out(void); */ void z_mem_manage_init(void); -/* Workaround for build-time page table mapping of the kernel */ -void z_kernel_map_fixup(void); - #define LOCKED(lck) for (k_spinlock_key_t __i = {}, \ __key = k_spin_lock(lck); \ !__i.key; \ diff --git a/kernel/init.c b/kernel/init.c index 3448dde5584..f7d05e18110 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -382,9 +382,6 @@ FUNC_NORETURN void z_cstart(void) struct k_thread dummy_thread; z_dummy_thread_init(&dummy_thread); -#endif -#if defined(CONFIG_MMU) && defined(CONFIG_USERSPACE) - z_kernel_map_fixup(); #endif /* do any necessary initialization of static devices */ z_device_state_init(); diff --git a/kernel/mmu.c b/kernel/mmu.c index baab6b455d0..85dbdc06ace 100644 --- a/kernel/mmu.c +++ b/kernel/mmu.c @@ -486,30 +486,6 @@ size_t k_mem_region_align(uintptr_t *aligned_addr, size_t *aligned_size, return addr_offset; } - -#ifdef CONFIG_USERSPACE -void z_kernel_map_fixup(void) -{ - /* XXX: Gperf kernel object data created at build time will not have - * visibility in zephyr_prebuilt.elf. There is a possibility that this - * data would not be memory-mapped if it shifts z_mapped_end between - * builds. Ensure this area is mapped. - * - * A third build phase for page tables would solve this. - */ - uint8_t *kobject_page_begin = - (uint8_t *)ROUND_DOWN((uintptr_t)&z_kobject_data_begin, - CONFIG_MMU_PAGE_SIZE); - size_t kobject_size = (size_t)(Z_KERNEL_VIRT_END - kobject_page_begin); - - if (kobject_size != 0U) { - arch_mem_map(kobject_page_begin, - Z_BOOT_VIRT_TO_PHYS(kobject_page_begin), - kobject_size, K_MEM_PERM_RW | K_MEM_CACHE_WB); - } -} -#endif /* CONFIG_USERSPACE */ - void z_mem_manage_init(void) { uintptr_t phys; diff --git a/scripts/gen_kobject_placeholders.py b/scripts/gen_kobject_placeholders.py new file mode 100755 index 00000000000..bd529bc16cd --- /dev/null +++ b/scripts/gen_kobject_placeholders.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2021 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +""" +Process ELF file to generate placeholders for kobject +hash table and lookup functions produced by gperf, +since their sizes depend on how many kobjects have +been declared. The output header files will be used +during linking for intermediate output binaries so +that the addresses of these kobjects would remain +the same during later stages of linking. +""" + +import sys +import argparse +import os +from distutils.version import LooseVersion + +import elftools +from elftools.elf.elffile import ELFFile + + +if LooseVersion(elftools.__version__) < LooseVersion('0.24'): + sys.exit("pyelftools is out of date, need version 0.24 or later") + + +def write_define(out_fp, prefix, name, value): + """Write the #define to output file""" + define_name = f"KOBJECT_{prefix}_{name}" + out_fp.write(f"#ifndef {define_name}\n") + out_fp.write(f"#define {define_name} {value}\n") + out_fp.write("#endif\n\n") + + +def output_simple_header(one_sect): + """Write the header for kobject section""" + + out_fn = os.path.join(args.outdir, + f"linker-kobject-prebuilt-{one_sect['name']}.h") + out_fp = open(out_fn, "w") + + if one_sect['exists']: + align = one_sect['align'] + size = one_sect['size'] + prefix = one_sect['define_prefix'] + + write_define(out_fp, prefix, 'ALIGN', align) + write_define(out_fp, prefix, 'SZ', size) + + out_fp.close() + + +def generate_linker_headers(obj): + """Generate linker header files to be included by the linker script""" + + # Sections we are interested in + sections = { + ".data": { + "name": "data", + "define_prefix": "DATA", + "exists": False, + "multiplier": int(args.datapct) + 100, + }, + ".rodata": { + "name": "rodata", + "define_prefix": "RODATA", + "exists": False, + "extra_bytes": args.rodata, + }, + ".priv_stacks.noinit": { + "name": "priv-stacks", + "define_prefix": "PRIV_STACKS", + "exists": False, + }, + } + + for one_sect in obj.iter_sections(): + # REALLY NEED to match exact type as all other sections + # (symbol, debug, etc.) are descendants where + # isinstance() would match. + if type(one_sect) is not elftools.elf.sections.Section: # pylint: disable=unidiomatic-typecheck + continue + + name = one_sect.name + if name in sections.keys(): + # Need section alignment and size + sections[name]['align'] = one_sect['sh_addralign'] + sections[name]['size'] = one_sect['sh_size'] + sections[name]['exists'] = True + + if "multiplier" in sections[name]: + sections[name]['size'] *= sections[name]['multiplier'] / 100 + sections[name]['size'] = int(sections[name]['size']) + + if "extra_bytes" in sections[name]: + sections[name]['size'] += int(sections[name]['extra_bytes']) + + for one_sect in sections: + output_simple_header(sections[one_sect]) + + +def parse_args(): + """Parse command line arguments""" + global args + + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + + parser.add_argument("--object", required=True, + help="Points to kobject_prebuilt_hash.c.obj") + parser.add_argument("--outdir", required=True, + help="Output directory (/include/generated)") + parser.add_argument("--datapct", required=True, + help="Multipler to the size of reserved space for DATA region") + parser.add_argument("--rodata", required=True, + help="Extra bytes to reserve for RODATA region") + parser.add_argument("-v", "--verbose", action="store_true", + help="Verbose messages") + args = parser.parse_args() + if "VERBOSE" in os.environ: + args.verbose = 1 + + +def main(): + """Main program""" + parse_args() + + with open(args.object, "rb") as obj_fp: + obj = ELFFile(obj_fp) + + generate_linker_headers(obj) + + +if __name__ == "__main__": + main()